package com.xbongbong.paas.service.stage.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Maps;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.business.rule.BusinessRuleConditionHelp;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.StageLogEntity;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.domain.entity.StageWorkflowEntity;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EnableEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.StageChangeTypeEnum;
import com.xbongbong.paas.enums.StageProcessVersionTypeEnum;
import com.xbongbong.paas.enums.StageSettingEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.FilterConditionsPoJo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.StageProcessModel;
import com.xbongbong.paas.model.StageWorkflowModel;
import com.xbongbong.paas.pojo.StageDefaultAndLinkOptionItemPojo;
import com.xbongbong.paas.pojo.StageDefaultAndLinkOptionSavePojo;
import com.xbongbong.paas.pojo.StageFindPojo;
import com.xbongbong.paas.pojo.StageListPojo;
import com.xbongbong.paas.pojo.StageProcessGetPojo;
import com.xbongbong.paas.pojo.StageProcessVersionPojo;
import com.xbongbong.paas.pojo.StageSavePojo;
import com.xbongbong.paas.pojo.StageWorkPojo;
import com.xbongbong.paas.pojo.dto.OpportunityStageAddDTO;
import com.xbongbong.paas.pojo.dto.StageDefaultAndLinkOptionSaveDTO;
import com.xbongbong.paas.pojo.dto.StageProcessAddDTO;
import com.xbongbong.paas.pojo.dto.StageProcessArchiveDTO;
import com.xbongbong.paas.pojo.dto.StageProcessDeleteDTO;
import com.xbongbong.paas.pojo.dto.StageProcessEnableDTO;
import com.xbongbong.paas.pojo.dto.StageProcessGetDTO;
import com.xbongbong.paas.pojo.dto.StageProcessGetExceptDTO;
import com.xbongbong.paas.pojo.dto.StageProcessSaveDTO;
import com.xbongbong.paas.pojo.dto.StageProcessSortDTO;
import com.xbongbong.paas.pojo.dto.StageProcessVersionDTO;
import com.xbongbong.paas.pojo.dto.StageRatioAttrNameGetDTO;
import com.xbongbong.paas.pojo.dto.StageRatioAttrNameSetDTO;
import com.xbongbong.paas.pojo.dto.StageSaveDTO;
import com.xbongbong.paas.pojo.dto.StageWorkGetDTO;
import com.xbongbong.paas.pojo.dto.StageWorkSaveDTO;
import com.xbongbong.paas.pojo.dto.StageWorkSortDTO;
import com.xbongbong.paas.pojo.vo.StageProcessArchiveVO;
import com.xbongbong.paas.pojo.vo.StageProcessEnableVO;
import com.xbongbong.paas.pojo.vo.StageProcessGetExceptVO;
import com.xbongbong.paas.pojo.vo.StageProcessGetVO;
import com.xbongbong.paas.pojo.vo.StageProcessVersionVO;
import com.xbongbong.paas.pojo.vo.StageRatioAttrNameGetVO;
import com.xbongbong.paas.service.stage.AbstractStageSettingsStrategy;
import com.xbongbong.paas.service.stage.StageHandle;
import com.xbongbong.paas.service.stage.StageHandleFactory;
import com.xbongbong.paas.service.stage.StageLogHandle;
import com.xbongbong.paas.service.stage.StageLogHandleFactory;
import com.xbongbong.paas.service.stage.StageProcessService;
import com.xbongbong.paas.service.stage.StageSettingsFactory;
import com.xbongbong.paas.service.stage.StageSettingsStrategy;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.businesstage.pojo.SortPojo;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.StageProcessConstant;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BusinessTypeErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.CustomerStageErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.WorkOrderErrorCodeEnum;
import com.xbongbong.pro.service.stage.StageFindStrategy;
import com.xbongbong.pro.service.stage.factory.StageFindFactory;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.StageWorkEntity;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.dictionary.ArchivedEnum;
import com.xbongbong.saas.help.StageHelp;
import com.xbongbong.saas.model.SaleStageModifyLogModel;
import com.xbongbong.saas.model.StageWorkModel;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 阶段流程
 * @author 李少杰
 * @version v1.0.0
 * @date 2021/11/18 15:08
 */
@Service("stageProcessService")
public class StageProcessServiceImpl implements StageProcessService {

    private static final Logger LOG = LoggerFactory.getLogger(StageProcessServiceImpl.class);

    @Resource
    private StageProcessModel stageProcessModel;
    @Resource
    private StageHandleFactory stageHandleFactory;
    @Resource
    private StageLogHandleFactory stageLogHandleFactory;
    @Resource
    private StageHelp stageHelp;
    @Resource
    private StageWorkModel stageWorkModel;
    @Resource
    private AbstractStageSettingsStrategy abstractStageSettingsStrategy;
    @Resource
    private StageSettingsFactory stageSettingsFactory;
    @Resource
    private SaleStageModifyLogModel saleStageModifyLogModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private StageWorkflowModel stageWorkflowModel;

    @Override
    public StageProcessVersionVO stageProcessVersion(StageProcessVersionDTO stageProcessVersionDTO) throws XbbException {
        StageProcessVersionVO stageProcessVersionVO = new StageProcessVersionVO();

        String corpid = stageProcessVersionDTO.getCorpid();
        Long formId = stageProcessVersionDTO.getFormId();
        Integer archive = stageProcessVersionDTO.getArchive();
        Integer businessType = stageProcessVersionDTO.getBusinessType();
        Integer saasMark = stageProcessVersionDTO.getSaasMark();
        Long defaultStageProcessId = stageHelp.getMultiVersionDefaultStageProcess(corpid, formId);

        try {
            if (Objects.isNull(businessType) && !Objects.equals(saasMark, SaasMarkEnum.PAAS.getCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.BUSINESS_TYPE_NOT_NULL);
            }
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID, corpid);
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            params.put(StringConstant.FORM_ID, formId);
            params.put(ParameterConstant.ORDER_BY_STR, " version_id " + SortOrder.ASC);
            params.put(ParameterConstant.IS_ARCHIVE, archive);
            Integer entitysCount = 0;
            Integer pageSize = stageProcessVersionDTO.getPageSize();
            Integer page = stageProcessVersionDTO.getPage();
            if (Objects.equals(archive, ArchivedEnum.ARCHIVED.getCode())) {
                entitysCount = stageProcessModel.getEntitysCount(params);
                params.put(ParameterConstant.START, (page - 1) * pageSize);
                params.put(ParameterConstant.PAGE_NUM, pageSize);
            }
            List<StageProcessEntity> stageProcessEntityList = stageProcessModel.findEntitys(params);
            Set<Long> haveWorkSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (Objects.equals(archive, ArchivedEnum.UN_ARCHIVED.getCode())) {
                if (CollectionsUtil.isNotEmpty(stageProcessEntityList)) {
                    List<Long> stageProcessIdIn = stageProcessEntityList.stream().map(StageProcessEntity::getId).collect(Collectors.toList());
                    if (CollectionsUtil.isNotEmpty(stageProcessIdIn)) {
                        StageLogHandle stageLogHandle = stageLogHandleFactory.getStageLogHandle(saasMark, businessType);
                        List<Long> stageLogEntityList = stageLogHandle.findUsedStageProcessId(corpid, formId, stageProcessIdIn);
                        haveWorkSet.addAll(stageLogEntityList);
                    }
                }
            }
            List<StageProcessVersionPojo> stageProcessVersionPojoList = new ArrayList<>();
            List<StageProcessVersionPojo> stageEnableProcessVersionPojoList = new ArrayList<>();
            List<StageProcessVersionPojo> stageNormalProcessVersionPojoList = new ArrayList<>();
            for (StageProcessEntity stageProcessEntity : stageProcessEntityList) {
                StageProcessVersionPojo stageProcessVersionPojo = new StageProcessVersionPojo();
                stageProcessVersionPojo.setId(stageProcessEntity.getId());
                stageProcessVersionPojo.setVersionName(stageProcessEntity.getVersionName());
                stageProcessVersionPojo.setVersionId(stageProcessEntity.getVersionId());
                stageProcessVersionPojo.setEnable(stageProcessEntity.getEnable());
                stageProcessVersionPojo.setIsArchive(stageProcessEntity.getIsArchive());
                stageProcessVersionPojo.setPriority(stageProcessEntity.getPriority());
                stageProcessVersionPojo.setDefaultVersion(Objects.equals(stageProcessEntity.getId(), defaultStageProcessId) ? 1 : 0);
                if (Objects.equals(stageProcessEntity.getEnable(), EnableEnum.OPEN.getCode())) {
                    stageProcessVersionPojo.setType(StageProcessVersionTypeEnum.ENABLE.getCode());
                    stageEnableProcessVersionPojoList.add(stageProcessVersionPojo);
                } else {
                    if (haveWorkSet.contains(stageProcessEntity.getId())) {
                        stageProcessVersionPojo.setType(StageProcessVersionTypeEnum.HISTORY.getCode());
                    } else {
                        stageProcessVersionPojo.setType(StageProcessVersionTypeEnum.DESIGN.getCode());
                    }
                    stageNormalProcessVersionPojoList.add(stageProcessVersionPojo);
                }
            }
            if (CollectionsUtil.isNotEmpty(stageEnableProcessVersionPojoList)) {
                // 启用的版本按照优先级进行排序，优先级高的排序在前面
                stageEnableProcessVersionPojoList = stageEnableProcessVersionPojoList.stream().sorted(Comparator.comparing(StageProcessVersionPojo::getPriority)).collect(Collectors.toList());
            }
            stageProcessVersionPojoList.addAll(stageEnableProcessVersionPojoList);
            stageProcessVersionPojoList.addAll(stageNormalProcessVersionPojoList);
            List<String> filterValue = stageProcessVersionDTO.getFilterValue();
            if (CollectionsUtil.isNotEmpty(filterValue)) {
                StageFindStrategy stageFindStrategy = StageFindFactory.getStageFindStrategy(saasMark, businessType);
                List<? extends PaasStageEntity> stageList = stageFindStrategy.findStageList(corpid, new StageFindPojo(formId, null, filterValue));
                List<List> filterValueFormat = new ArrayList<>();
                for (PaasStageEntity paasStageEntity : stageList) {
                    filterValueFormat.add(Arrays.asList(paasStageEntity.getStageProcessId(), paasStageEntity.getCode()));
                }
                stageProcessVersionVO.setFilterValueFormat(filterValueFormat);
            }
            PageHelper pageHelper = new PageHelper(page, pageSize);
            pageHelper.setRowsCount(entitysCount);
            stageProcessVersionVO.setPageHelper(pageHelper);
            stageProcessVersionVO.setStageProcessVersionPojoList(stageProcessVersionPojoList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("stageProcessVersion 获取流程版本出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return stageProcessVersionVO;
    }

    @Override
    public StageProcessVersionVO currentEnableVersion(StageProcessVersionDTO stageProcessVersionDTO) throws XbbException {
        StageProcessVersionVO stageProcessVersionVO = new StageProcessVersionVO();

        String corpid = stageProcessVersionDTO.getCorpid();
        Long formId = stageProcessVersionDTO.getFormId();
        Integer businessType = stageProcessVersionDTO.getBusinessType();
        Integer saasMark = stageProcessVersionDTO.getSaasMark();

        try {
            if (Objects.isNull(businessType) && !Objects.equals(saasMark, SaasMarkEnum.PAAS.getCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.BUSINESS_TYPE_NOT_NULL);
            }
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID, corpid);
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            params.put(StringConstant.FORM_ID, formId);
            params.put(ParameterConstant.ORDER_BY_STR, " enable " + SortOrder.DESC  + ", priority " + SortOrder.ASC + ", version_id " + SortOrder.ASC);
            params.put(ParameterConstant.IS_ARCHIVE, ArchivedEnum.UN_ARCHIVED.getCode());
            params.put(ParameterConstant.START, 0);
            params.put(ParameterConstant.PAGE_NUM, 1);
            List<StageProcessEntity> stageProcessEntityList = stageProcessModel.findEntitys(params);

            List<StageProcessVersionPojo> stageProcessVersionPojoList = new ArrayList<>();
            if (CollectionsUtil.isNotEmpty(stageProcessEntityList)) {
                Long defaultStageProcessId = stageHelp.getMultiVersionDefaultStageProcess(corpid, formId);
                StageProcessEntity stageProcessEntity = stageProcessEntityList.get(0);
                StageProcessVersionPojo stageProcessVersionPojo = new StageProcessVersionPojo();
                stageProcessVersionPojo.setId(stageProcessEntity.getId());
                stageProcessVersionPojo.setVersionName(stageProcessEntity.getVersionName());
                stageProcessVersionPojo.setVersionId(stageProcessEntity.getVersionId());
                stageProcessVersionPojo.setEnable(stageProcessEntity.getEnable());
                stageProcessVersionPojo.setIsArchive(stageProcessEntity.getIsArchive());
                stageProcessVersionPojo.setPriority(stageProcessEntity.getPriority());
                stageProcessVersionPojo.setDefaultVersion(Objects.equals(stageProcessEntity.getId(), defaultStageProcessId) ? 1 : 0);
                if (Objects.equals(stageProcessEntity.getEnable(), EnableEnum.OPEN.getCode())) {
                    stageProcessVersionPojo.setType(StageProcessVersionTypeEnum.ENABLE.getCode());
                } else {
                    params.remove(ParameterConstant.ORDER_BY_STR);
                    params.remove(ParameterConstant.IS_ARCHIVE);
                    params.remove(ParameterConstant.START);
                    params.remove(ParameterConstant.PAGE_NUM);
                    params.put("stageProcessId", stageProcessEntity.getId());

                    StageLogHandle stageLogHandle = stageLogHandleFactory.getStageLogHandle(saasMark, businessType);
                    Integer stageLogCount = stageLogHandle.getEntitysCount(params);
                    if (stageLogCount > 0) {
                        stageProcessVersionPojo.setType(StageProcessVersionTypeEnum.HISTORY.getCode());
                    } else {
                        stageProcessVersionPojo.setType(StageProcessVersionTypeEnum.DESIGN.getCode());
                    }
                }
                stageProcessVersionPojoList.add(stageProcessVersionPojo);
            }

            PageHelper pageHelper = new PageHelper(1, 1);
            pageHelper.setRowsCount(1);
            stageProcessVersionVO.setPageHelper(pageHelper);
            stageProcessVersionVO.setStageProcessVersionPojoList(stageProcessVersionPojoList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("currentEnableVersion 获取当前流程版本出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return stageProcessVersionVO;
    }

    @Override
    public BaseVO setStageDefaultAndLinkOption(StageDefaultAndLinkOptionSaveDTO stageDefaultAndLinkOptionSaveDTO) throws XbbException {
        List<StageDefaultAndLinkOptionSavePojo> stageDefaultAndLinkOptionSavePojoList = stageDefaultAndLinkOptionSaveDTO.getStageDefaultAndLinkOptionSavePojoList();
        if (CollectionsUtil.isEmpty(stageDefaultAndLinkOptionSavePojoList)) {
            return new BaseVO();
        }

        String corpid = stageDefaultAndLinkOptionSaveDTO.getCorpid();
        Long formId = stageDefaultAndLinkOptionSaveDTO.getFormId();
        Integer saasMark = stageDefaultAndLinkOptionSaveDTO.getSaasMark();
        Integer businessType = stageDefaultAndLinkOptionSaveDTO.getBusinessType();
        List<Long> stageProcessIdList = stageDefaultAndLinkOptionSavePojoList.stream().map(StageDefaultAndLinkOptionSavePojo::getStageProcessId).collect(Collectors.toList());

        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put(StringConstant.FORM_ID, formId);
        params.put("stageProcessIdIn", stageProcessIdList);
        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        List<PaasStageEntity> stageList = stageHandle.findEntitys(params);

        for (PaasStageEntity paasStageEntity : stageList) {
            for (StageDefaultAndLinkOptionSavePojo stageDefaultAndLinkOptionSavePojo : stageDefaultAndLinkOptionSavePojoList) {
                Long stageProcessId = stageDefaultAndLinkOptionSavePojo.getStageProcessId();
                List<StageDefaultAndLinkOptionItemPojo> stageDefaultAndLinkOptionItemPojoList = stageDefaultAndLinkOptionSavePojo.getStageList();
                if (CollectionsUtil.isEmpty(stageDefaultAndLinkOptionItemPojoList)) {
                    continue;
                }
                for (StageDefaultAndLinkOptionItemPojo stageDefaultAndLinkOptionItemPojo : stageDefaultAndLinkOptionItemPojoList) {
                    if (Objects.equals(paasStageEntity.getStageProcessId(), stageProcessId) && Objects.equals(paasStageEntity.getId(), stageDefaultAndLinkOptionItemPojo.getId())) {
                        paasStageEntity.setIsDefault(stageDefaultAndLinkOptionItemPojo.getIsDefault());
                        paasStageEntity.setLinkOption(stageDefaultAndLinkOptionItemPojo.getLinkOption());
                    }
                }
            }
        }
        if (CollectionsUtil.isNotEmpty(stageList)) {
            stageHandle.updateBatchDefaultAndLinkOption(stageList, corpid);
        }
        return new BaseVO();
    }

    @Override
    public StageProcessGetVO get(StageProcessGetDTO stageProcessGetDTO) throws XbbException {
        StageProcessGetVO stageProcessGetVO = new StageProcessGetVO();
        String corpid = stageProcessGetDTO.getCorpid();
        Integer saasMark = stageProcessGetDTO.getSaasMark();
        Integer businessType = stageProcessGetDTO.getBusinessType();
        Long formId = stageProcessGetDTO.getFormId();
        Long id = stageProcessGetDTO.getId();
        try {
            // 获取流程
            stageHelp.checkPaasAndNoUltimate(corpid, saasMark);
            Long stageProcessId = stageProcessGetDTO.getId();
            StageProcessEntity stageProcessEntity = stageProcessModel.getByKey(stageProcessId, corpid);
            if (Objects.isNull(stageProcessEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_PROCESS_NOT_EXIST);
            }
            StageProcessGetPojo stageProcessGetPojo = getStageProcessGetPojo(stageProcessEntity);
            stageProcessGetPojo.setType(stageProcessGetDTO.getType());
            stageProcessGetVO.setStageProcessGetPojo(stageProcessGetPojo);
            Long defaultStageProcessId = stageHelp.getMultiVersionDefaultStageProcess(corpid, formId);
            stageProcessGetPojo.setDefaultVersion(Objects.equals(stageProcessEntity.getId(), defaultStageProcessId) ? 1 : 0);

            // 获取阶段列表
            List<PaasStageEntity> stageEntitys = stageHelp.getStageEntitys(corpid, saasMark, businessType, formId, id);
            StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
            List<StageListPojo> stageListPojoList = stageHelp.getStageListPojo(stageEntitys, null, stageHandle, StageSettingEnum.MAIN.getCode());

            stageProcessGetVO.setStageListPojoList(stageListPojoList);

        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("stageProcess 数据库获取流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return stageProcessGetVO;
    }

    @Override
    public BaseVO sort(StageProcessSortDTO stageProcessSortDTO) throws XbbException {
        try {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, stageProcessSortDTO.getCorpid());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(StringConstant.FORM_ID, stageProcessSortDTO.getFormId());
            List<StageProcessEntity> stageProcessList = stageProcessModel.findEntitys(param);
            List<Long> dbStageProcessIdList = stageProcessList.stream().map(StageProcessEntity::getId).collect(Collectors.toList());
            ArrayList<Long> pageStageProcessIdList = stageProcessSortDTO.getStageProcessIdList();
            if (Objects.equals(pageStageProcessIdList.size(), dbStageProcessIdList.size()) && pageStageProcessIdList.containsAll(dbStageProcessIdList)) {
                for (StageProcessEntity stageProcess : stageProcessList) {
                    for (Long stageProcessId : pageStageProcessIdList) {
                        if (Objects.equals(stageProcess.getId(), stageProcessId)) {
                            Integer index = pageStageProcessIdList.indexOf(stageProcessId) + 1;
                            stageProcess.setPriority(index);
                        }
                    }
                }
                stageProcessModel.updateBatchPriority(stageProcessList, stageProcessSortDTO.getCorpid());
            }
        } catch (Exception e) {
            LOG.error("StageProcessServiceImpl.sort error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return new BaseVO();
    }

    @Override
    public StageProcessGetExceptVO getAll(StageProcessGetExceptDTO stageProcessGetExceptDTO) throws XbbException {
        // 获取流程版本内所有启用的阶段列表 - 不剔除任何
        List<? extends PaasStageEntity> stageList = getPaasStageList(stageProcessGetExceptDTO, null);
        StageProcessGetExceptVO stageProcessGetExceptVO = new StageProcessGetExceptVO();
        stageProcessGetExceptVO.setStageList(stageList);
        return stageProcessGetExceptVO;
    }

    @Override
    public StageProcessGetExceptVO getExceptCancel(StageProcessGetExceptDTO stageProcessGetExceptDTO) throws XbbException {
        // 获取流程版本内所有启用的阶段列表 - 剔除取消
        List<Integer> typeIn = StageTypeEnum.getExceptCancelType();
        stageProcessGetExceptDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
        stageProcessGetExceptDTO.setBusinessType(XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
        List<? extends PaasStageEntity> stageList = getPaasStageList(stageProcessGetExceptDTO, typeIn);
        StageProcessGetExceptVO stageProcessGetExceptVO = new StageProcessGetExceptVO();
        stageProcessGetExceptVO.setStageList(stageList);
        return stageProcessGetExceptVO;
    }

    @Override
    public StageProcessGetExceptVO getExceptLoseCancel(StageProcessGetExceptDTO stageProcessGetExceptDTO) throws XbbException {
        // 获取流程版本内所有启用的阶段列表 - 剔除失败、取消
        List<Integer> typeIn = StageTypeEnum.getExceptLoseCancelType();
        stageProcessGetExceptDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
        stageProcessGetExceptDTO.setBusinessType(XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
        List<? extends PaasStageEntity> stageList = getPaasStageList(stageProcessGetExceptDTO, typeIn);
        StageProcessGetExceptVO stageProcessGetExceptVO = new StageProcessGetExceptVO();
        stageProcessGetExceptVO.setStageList(stageList);
        return stageProcessGetExceptVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StageProcessEnableVO enable(StageProcessEnableDTO stageProcessEnableDTO) throws XbbException {
        StageProcessEnableVO stageProcessEnableVO = new StageProcessEnableVO();
        Long id = stageProcessEnableDTO.getId();
        String corpid = stageProcessEnableDTO.getCorpid();
        Integer saasMark = stageProcessEnableDTO.getSaasMark();
        Integer businessType = stageProcessEnableDTO.getBusinessType();
        Long formId = stageProcessEnableDTO.getFormId();
        // 是否开启阶段推进器多版本启用，0不是，1是
        Integer stageMultiVersion = stageProcessEnableDTO.getStageMultiVersion();
        // 开启了阶段推进器多版本启用后设置的默认版本
        Long defaultStageProcessId = stageProcessEnableDTO.getDefaultStageProcessId();

        StageProcessEntity oldStageProcessEntity = new StageProcessEntity();
        StageProcessEntity newStageProcessEntity = null;
        try {
            stageHelp.checkPaasAndNoUltimate(corpid, saasMark);
            StageProcessEntity stageProcessEntity = stageProcessModel.getByKey(id, corpid);
            if (Objects.isNull(stageProcessEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_PROCESS_NOT_EXIST);
            }
            BeanUtil.copyProperties(stageProcessEntity, oldStageProcessEntity);
            if (Objects.equals(stageProcessEnableDTO.getEnable(), EnableEnum.OPEN.getCode())) {
                List<PaasStageEntity> stageEnableEntityList = stageHelp.getStageEnableEntitys(corpid, saasMark, businessType, formId, id);
                abstractStageSettingsStrategy.stageNormalCheck(businessType, stageEnableEntityList);
                checkStage(stageEnableEntityList, businessType);
                List<StageWorkEntity> stageWorkEntityList = stageHelp.getStageWorkEntityByProcess(corpid, formId, id);
                Map<Long, List<StageWorkEntity>> stageWorkEntityMap = stageWorkEntityList.stream().collect(Collectors.groupingBy(StageWorkEntity::getStageId));
                for (PaasStageEntity paasStageEntity : stageEnableEntityList) {
                    abstractStageSettingsStrategy.checkStageWork(paasStageEntity, stageWorkEntityMap.get(paasStageEntity.getId()));
                }
                Map<String, Object> params = Maps.newHashMapWithExpectedSize(2 << 1);
                params.put(StringConstant.CORPID, stageProcessEnableDTO.getCorpid());
                params.put(StringConstant.FORM_ID, stageProcessEnableDTO.getFormId());
                params.put(ParameterConstant.ENABLE, stageProcessEnableDTO.getEnable());
                params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                List<StageProcessEntity> stageProcessEntityList = stageProcessModel.findEntitys(params);
                if (Objects.equals(stageMultiVersion, 1)) {
                    // 多版本启用时校验同时启用的版本数量
                    if (CollectionsUtil.isNotEmpty(stageProcessEntityList) && stageProcessEntityList.size() >= StageProcessConstant.ENABLE_STAGE_PROCESS_MAX_COUNT) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238074);
                    }
                } else {
                    // 单版本启用时，将其他版本设置为关闭
                    if (CollectionsUtil.isNotEmpty(stageProcessEntityList)) {
                        stageProcessEntityList.forEach(item -> item.setEnable(EnableEnum.CLOSE.getCode()));
                        stageProcessModel.updateBatch(stageProcessEntityList, stageProcessEnableDTO.getCorpid());
                    }
                }
            }
            stageProcessEntity.setEnable(stageProcessEnableDTO.getEnable());
            newStageProcessEntity = stageProcessEntity;
            stageProcessModel.update(stageProcessEntity);

            // 保存多版本启用的开关状态
            PaasFormExplainEntity formExplain = paasFormExplainModel.getByFormId(formId, corpid);
            List<FieldAttrEntity> explainList = JSON.parseArray(formExplain.getExplains(), FieldAttrEntity.class);
            explainList.forEach(fieldAttrEntity -> {
                if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.STAGE_THRUSTER.getType())) {
                    fieldAttrEntity.setStageMultiVersion(stageMultiVersion);
                    fieldAttrEntity.setDefaultStageProcessId(defaultStageProcessId);
                }
            });
            formExplain.setExplains(JSON.toJSONString(explainList));
            // 表单解释保存之前，校验多版本启用时设置的默认版本是否合法
            validateMultiVersionDefaultStageProcess(explainList, corpid, formId);
            paasFormExplainModel.update(formExplain);

            stageProcessEnableVO.setId(stageProcessEnableDTO.getId());
            stageProcessEnableVO.setDistributorMark(stageProcessEnableDTO.getDistributorMark());
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("stageProcess 数据库启用/暂停流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        // 记录日志
        abstractStageSettingsStrategy.saveStageProcessLog(stageProcessEnableDTO, formId, Collections.singletonList(oldStageProcessEntity), Collections.singletonList(newStageProcessEntity));
        return stageProcessEnableVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StageProcessArchiveVO archive(StageProcessArchiveDTO stageProcessArchiveDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();
        try {
            // 获取相应的归档状态的数量
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID, stageProcessArchiveDTO.getCorpid());
            params.put(StringConstant.FORM_ID, stageProcessArchiveDTO.getFormId());
            params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.IS_ARCHIVE, ArchivedEnum.UN_ARCHIVED.getCode());
            Integer noArchive = stageProcessModel.getEntitysCount(params);
            if (Objects.equals(noArchive, BasicConstant.ONE)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NON_ARCHIVE_LEAST);
            }
            params.put(ParameterConstant.IS_ARCHIVE, ArchivedEnum.ARCHIVED.getCode());
            Integer count = stageProcessModel.getEntitysCount(params);
            // 未归档版本限制30个
            if (count >= StageProcessConstant.ARCHIVE_MAX_COUNT) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_ARCHIVE_MAX_LIMIT);
            }

            // 修改流程版本归档状态
            StageProcessEntity stageProcessEntity = new StageProcessEntity();
            stageProcessEntity.setId(stageProcessArchiveDTO.getId());
            stageProcessEntity.setCorpid(stageProcessArchiveDTO.getCorpid());
            stageProcessEntity.setFormId(stageProcessArchiveDTO.getFormId());
            stageProcessEntity.setIsArchive(ArchivedEnum.ARCHIVED.getCode());
            stageProcessModel.update(stageProcessEntity);

            stageProcessArchiveVO.setId(stageProcessArchiveDTO.getId());
            stageProcessArchiveVO.setDistributorMark(stageProcessArchiveDTO.getDistributorMark());
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("stageProcess 流程归档出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        // TODO 记录日志

        return stageProcessArchiveVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StageProcessArchiveVO cancelArchive(StageProcessArchiveDTO stageProcessArchiveDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();
        try {

            Map<String, Object> params = Maps.newHashMapWithExpectedSize(5);
            params.put(StringConstant.CORPID, stageProcessArchiveDTO.getCorpid());
            params.put(StringConstant.FORM_ID, stageProcessArchiveDTO.getFormId());
            params.put(ParameterConstant.ID, stageProcessArchiveDTO.getId());
            params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.IS_ARCHIVE, ArchivedEnum.UN_ARCHIVED.getCode());

            Integer count = stageProcessModel.getEntitysCount(params);
            // 归档版本限制30个
            if (count >= StageProcessConstant.ARCHIVE_MAX_COUNT) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NON_ARCHIVE_MAX_LIMIT);
            }

            // 修改流程版本归档状态
            StageProcessEntity stageProcessEntity = new StageProcessEntity();
            stageProcessEntity.setId(stageProcessArchiveDTO.getId());
            stageProcessEntity.setCorpid(stageProcessArchiveDTO.getCorpid());
            stageProcessEntity.setFormId(stageProcessArchiveDTO.getFormId());
            stageProcessEntity.setIsArchive(ArchivedEnum.UN_ARCHIVED.getCode());
            stageProcessModel.update(stageProcessEntity);

            stageProcessArchiveVO.setId(stageProcessArchiveDTO.getId());
            stageProcessArchiveVO.setDistributorMark(stageProcessArchiveDTO.getDistributorMark());
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库删除流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        // TODO 记录日志
        return stageProcessArchiveVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StageProcessArchiveVO delete(StageProcessDeleteDTO stageProcessDeleteDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();
        String corpid = stageProcessDeleteDTO.getCorpid();
        Integer businessType = stageProcessDeleteDTO.getBusinessType();
        Integer saasMark = stageProcessDeleteDTO.getSaasMark();
        Long formId = stageProcessDeleteDTO.getFormId();
        Long id = stageProcessDeleteDTO.getId();
        try {
            Integer stageLogCount = stageHelp.getStageLogCount(corpid, saasMark, businessType, formId, id);
            if (Objects.nonNull(stageLogCount) && !Objects.equals(stageLogCount, BasicConstant.ZERO)) {
                throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238013);
            }

            //删除流程
            StageProcessEntity processEntity = stageProcessModel.getByKey(id, corpid);
            if (Objects.isNull(processEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_PROCESS_NOT_EXIST);
            }
            stageProcessModel.delete(processEntity);

            // 删除关联阶段
            Map<String, Object> params = Maps.newHashMapWithExpectedSize(5);
            params.put(StringConstant.CORPID, corpid);
            params.put(StringConstant.FORM_ID, formId);
            params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.STAGE_PROCESS_ID, id);
            StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
            List<PaasStageEntity> stageEntityList = stageHandle.findEntitys(params);
            if (CollectionsUtil.isNotEmpty(stageEntityList)) {
                stageHandle.deleteBatch(stageEntityList, corpid);
            }

            //删除关联阶段记录
            StageLogHandle stageLogHandle = stageLogHandleFactory.getStageLogHandle(saasMark, businessType);
            List<StageLogEntity> stageLogEntityList = stageLogHandle.findEntitys(params);
            if (CollectionsUtil.isNotEmpty(stageLogEntityList)) {
                stageLogHandle.deleteBatch(stageLogEntityList, corpid);
            }

            //删除关联阶段任务
            List<StageWorkEntity> stageWorkEntity = stageHelp.getStageWorkEntityByProcess(corpid, formId, id);
            if (CollectionsUtil.isNotEmpty(stageWorkEntity)) {
                List<Long> idList = stageWorkEntity.stream().map(StageWorkEntity :: getId).collect(Collectors.toList());
                stageWorkModel.deleteBatch(idList);
            }

            //删除自定义工作流
            List<StageWorkflowEntity> stageWorkflowEntityList = stageHelp.getStageWorkflowEntity(corpid, formId, id);
            if (CollectionsUtil.isNotEmpty(stageWorkflowEntityList)) {
                stageWorkflowModel.deleteBatch(stageWorkflowEntityList, corpid);
            }

            stageProcessArchiveVO.setId(stageProcessDeleteDTO.getId());
            stageProcessArchiveVO.setDistributorMark(stageProcessDeleteDTO.getDistributorMark());

            //删除日志
            abstractStageSettingsStrategy.saveStageProcessLog(stageProcessDeleteDTO, formId, Collections.singletonList(processEntity), null);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("StageProcess 数据库删除流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        return stageProcessArchiveVO;
    }

    /**
     * 阶段流程新建
     *
     * @param stageProcessAddDTO
     * @return
     * @throws XbbException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public StageProcessArchiveVO add(StageProcessAddDTO stageProcessAddDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();
        String corpid = stageProcessAddDTO.getCorpid();
        Long formId = stageProcessAddDTO.getFormId();
        Long id = stageProcessAddDTO.getId();
        try {
            stageHelp.checkPaasAndNoUltimate(corpid, stageProcessAddDTO.getSaasMark());
            //复制流程
            StageProcessEntity stageProcessEntity = getCopyStageProcess(corpid, formId, id);
            stageProcessEntity.setStageUnit(BasicConstant.TWO);
            stageProcessEntity.setAllowBack(BasicConstant.ZERO);
            stageProcessEntity.setAllowNewSelect(BasicConstant.ZERO);
            stageProcessEntity.setAllowNewSelectUser(null);
            stageProcessEntity.setShowTimeUse(BasicConstant.ZERO);
            stageProcessEntity.setShowTimeStay(BasicConstant.ZERO);
            stageProcessEntity.setShowWorkCompletion(BasicConstant.ZERO);
            stageProcessEntity.setShowAverageCompletionTime(BasicConstant.ZERO);
            stageProcessEntity.setTriggerCondition(null);
            stageProcessEntity.setIsArchive(BasicConstant.TWO);
            stageProcessModel.insert(stageProcessEntity);
            // 记录日志
            abstractStageSettingsStrategy.saveStageProcessLog(stageProcessAddDTO, formId, null, Collections.singletonList(stageProcessEntity));
            stageProcessArchiveVO.setId(stageProcessEntity.getId());
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("StageProcess.add 添加流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return stageProcessArchiveVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StageProcessArchiveVO copy(StageProcessAddDTO stageProcessAddDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();
        String corpid = stageProcessAddDTO.getCorpid();
        Integer saasMark = stageProcessAddDTO.getSaasMark();
        Long formId = stageProcessAddDTO.getFormId();
        Long id = stageProcessAddDTO.getId();
        try {
            stageHelp.checkPaasAndNoUltimate(corpid, saasMark);
            //复制流程
            StageProcessEntity stageProcessEntity = getCopyStageProcess(corpid, formId, id);
            stageProcessModel.insert(stageProcessEntity);

            //复制阶段和阶段任务
            copyStage(stageProcessAddDTO, stageProcessEntity);

            // 记录日志
            abstractStageSettingsStrategy.saveStageProcessLog(stageProcessAddDTO, formId, null, Collections.singletonList(stageProcessEntity));
            stageProcessArchiveVO.setId(stageProcessEntity.getId());
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("StageProcess.copy 添加流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return stageProcessArchiveVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StageProcessArchiveVO save(StageProcessSaveDTO stageProcessSaveDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();
        String corpid = stageProcessSaveDTO.getCorpid();
        Long formId = stageProcessSaveDTO.getFormId();
        Long id = stageProcessSaveDTO.getId();
        Integer saasMark = stageProcessSaveDTO.getSaasMark();
        Integer businessType = stageProcessSaveDTO.getBusinessType();
        List<StageSavePojo> stageSavePojoList = stageProcessSaveDTO.getStageList();

        StageProcessEntity stageProcessEntity;
        StageProcessEntity oldStageProcessEntity;
        List<PaasStageEntity> stageEntityList;
        List<PaasStageEntity> oldStageEntityList;

        try {
            stageHelp.checkPaasAndNoUltimate(corpid, saasMark);
            if (CollectionsUtil.isEmpty(stageSavePojoList) || stageSavePojoList.size() < BasicConstant.THREE) {
                throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238016);
            }
            oldStageProcessEntity= stageProcessModel.getByKey(id, corpid);
            oldStageEntityList = stageHelp.getStageEntitys(corpid, saasMark, businessType, formId, id);
            stageProcessEntity = getStageProcessEntity(stageProcessSaveDTO);
            checkStageProcess(stageProcessEntity);
            if (Objects.isNull(id)) {
                //阶段流程不管归档与未归档 最多只能存在30条
                Integer stageProcessCount = stageHelp.getStageProcessCount(corpid, formId);
                if (Objects.nonNull(stageProcessCount) && (stageProcessCount >= StageProcessConstant.STAGE_PROCESS_MAX_COUNT)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, String.format(I18nMessageUtil.getMessage(MessageConstant.STAGE_PROCESS_MAX_NUM), StageProcessConstant.STAGE_PROCESS_MAX_COUNT));
                }
                stageProcessEntity.setCreatorId(stageProcessSaveDTO.getUserId());
                stageProcessEntity.setOldTransferVersion(BasicConstant.ZERO);
                stageProcessEntity.setAddTime(DateTimeUtil.getInt());
                stageProcessEntity.setEnable(EnableEnum.CLOSE.getCode());
                stageProcessEntity.setUpdateTime(DateTimeUtil.getInt());
                stageProcessModel.insert(stageProcessEntity);
            } else {
                stageProcessEntity.setId(stageProcessSaveDTO.getId());
                stageProcessEntity.setUpdateTime(DateTimeUtil.getInt());
                stageProcessModel.update(stageProcessEntity);
            }
            StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
            stageEntityList = getPaasStageEntity(corpid, formId, stageProcessEntity.getId(), stageSavePojoList, stageHandle);
            saveStage(corpid, saasMark, businessType, formId, stageProcessEntity.getId(), stageEntityList);
            stageProcessArchiveVO.setId(stageProcessEntity.getId());
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("StageProcess.save 保存流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        // 记录日志
        abstractStageSettingsStrategy.saveStageProcessLog(stageProcessSaveDTO, formId, Collections.singletonList(oldStageProcessEntity), Collections.singletonList(stageProcessEntity));
        abstractStageSettingsStrategy.saveStageLog(stageProcessSaveDTO, formId, oldStageEntityList, stageEntityList);
        stageProcessArchiveVO.setDistributorMark(stageProcessSaveDTO.getDistributorMark());
        return stageProcessArchiveVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseVO updateStageRatioAttrName(StageRatioAttrNameSetDTO stageRatioAttrNameSetDTO) throws XbbException {

        String corpid = stageRatioAttrNameSetDTO.getCorpid();
        Long formId = stageRatioAttrNameSetDTO.getFormId();
        String attrName = stageRatioAttrNameSetDTO.getAttrName();
        String attrNameEn = stageRatioAttrNameSetDTO.getAttrNameEn();
        try {
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            if (Objects.isNull(paasFormExplainEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            if (StringUtil.isEmpty(attrName) || StringUtil.isEmpty(attrNameEn)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_RATIO_NAME);
            }
            List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            List<FieldAttrEntity> stageRatioList = fieldAttrEntityList.stream().filter(item -> Objects.equals(item.getFieldType(), FieldTypeEnum.STAGE_RATIO.getType())).collect(Collectors.toList());
            if (CollectionsUtil.isNotEmpty(stageRatioList)) {
                FieldAttrEntity fieldAttrEntity = stageRatioList.get(0);
                fieldAttrEntity.setAttrName(attrName);
                fieldAttrEntity.setAttrNameEn(attrNameEn);
                paasFormExplainEntity.setExplains(JSON.toJSONString(fieldAttrEntityList));
                paasFormExplainModel.update(paasFormExplainEntity);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("设置阶段比例字段名失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return new BaseVO();
    }

    @Override
    public StageRatioAttrNameGetVO getStageRatioAttrName(StageRatioAttrNameGetDTO stageRatioAttrNameGetDTO) throws XbbException {
        StageRatioAttrNameGetVO stageRatioAttrNameGetVO = new StageRatioAttrNameGetVO();

        String corpid = stageRatioAttrNameGetDTO.getCorpid();
        Long formId = stageRatioAttrNameGetDTO.getFormId();

        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(paasFormExplainEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        List<FieldAttrEntity> stageRatioList = fieldAttrEntityList.stream().filter(item -> Objects.equals(item.getFieldType(), FieldTypeEnum.STAGE_RATIO.getType())).collect(Collectors.toList());
        if (CollectionsUtil.isNotEmpty(stageRatioList)) {
            FieldAttrEntity fieldAttrEntity = stageRatioList.get(0);
            stageRatioAttrNameGetVO.setAttrName(fieldAttrEntity.getAttrName());
            stageRatioAttrNameGetVO.setAttr(fieldAttrEntity.getAttr());
            stageRatioAttrNameGetVO.setFieldType(fieldAttrEntity.getFieldType());
            stageRatioAttrNameGetVO.setAttrNameEn(fieldAttrEntity.getAttrNameEn());
        }
        return stageRatioAttrNameGetVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StageProcessArchiveVO opportunityStageAdd(OpportunityStageAddDTO opportunityStageAddDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();
        Integer operationType = opportunityStageAddDTO.getOperationType();
        StageChangeTypeEnum stageChangeTypeEnum = StageChangeTypeEnum.getByType(operationType);
        if (Objects.isNull(stageChangeTypeEnum)) {
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222005);
        }
        switch (stageChangeTypeEnum) {
            case STAGE_PROCESS_CHANGE:
                StageProcessSaveDTO stageProcessSave = opportunityStageAddDTO.getStageProcessSave();
                if (Objects.isNull(stageProcessSave)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
                }
                BeanUtil.copyProperties(opportunityStageAddDTO, stageProcessSave);
                return copyAndSaveStageProcess(stageProcessSave);
            case STAGE_CHANGE:
                StageSaveDTO stageSave = opportunityStageAddDTO.getStageSave();
                if (Objects.isNull(stageSave)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
                }
                BeanUtil.copyProperties(opportunityStageAddDTO, stageSave);
                return copyAndSaveStage(stageSave);
            case STAGE_WORK_CHANGE:
                StageWorkSaveDTO stageWorkSave = opportunityStageAddDTO.getStageWorkSave();
                if (Objects.isNull(stageWorkSave)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
                }
                BeanUtil.copyProperties(opportunityStageAddDTO, stageWorkSave);
                return copyAndSaveStageWork(stageWorkSave);
            case STAGE_WORK_DELETE:
                StageWorkGetDTO stageWorkDel = opportunityStageAddDTO.getStageWorkDel();
                if (Objects.isNull(stageWorkDel)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
                }
                BeanUtil.copyProperties(opportunityStageAddDTO, stageWorkDel);
                return copyAndDelStageWork(stageWorkDel);
            case STAGE_WORK_SORT:
                StageWorkSortDTO stageWorkSortDTO = opportunityStageAddDTO.getStageWorkSort();
                if (Objects.isNull(stageWorkSortDTO)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
                }
                BeanUtil.copyProperties(opportunityStageAddDTO, stageWorkSortDTO);
                return copyAndSortStageWork(stageWorkSortDTO);
            case STAGE_START_CHANGE:
                StageSaveDTO startStageSave = opportunityStageAddDTO.getStageSave();
                if (Objects.isNull(startStageSave)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
                }
                BeanUtil.copyProperties(opportunityStageAddDTO, startStageSave);
                return copyAndSaveStartStage(startStageSave);
            default:
                break;
        }
        return stageProcessArchiveVO;
    }

    /**
     * 开始阶段变更复制阶段流程
     * @param stageSaveDTO
     * @return
     * @throws XbbException
     */
    public StageProcessArchiveVO copyAndSaveStartStage(StageSaveDTO stageSaveDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();

        String corpid = stageSaveDTO.getCorpid();
        Long formId = stageSaveDTO.getFormId();
        Long stageProcessId = stageSaveDTO.getStageProcessId();
        Integer saasMark = stageSaveDTO.getSaasMark();
        Integer businessType = stageSaveDTO.getBusinessType();
        StageSavePojo stageSavePojo = stageSaveDTO.getStageSavePojo();

        if (Objects.isNull(stageSavePojo.getOutProportion())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_PROPORTION_NOT_NULL);
        }

        // 复制阶段流程
        StageProcessEntity stageProcessEntity = getCopyStageProcess(corpid, formId, stageProcessId);
        stageProcessModel.insert(stageProcessEntity);

        //复制阶段
        Long processEntityId = stageProcessEntity.getId();
        List<PaasStageEntity> stageEntityList = stageHelp.getStageEntitys(corpid, saasMark, businessType, formId, stageProcessId);
        if (CollectionsUtil.isEmpty(stageEntityList)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238016);
        }

        PaasStageEntity firstStageEntity = stageHelp.getFirstStageEntity(corpid, saasMark, businessType, formId, stageProcessId);
        if (Objects.isNull(firstStageEntity)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238019);
        }
        firstStageEntity.setIntoProportion(stageSavePojo.getOutProportion());

        //校验阶段
        StageSettingsStrategy stageSettingsStrategy = stageSettingsFactory.getStageSettingsStrategy(firstStageEntity.getType());
        List<PaasStageEntity> enableStageEntityList = stageEntityList.stream().filter(item -> Objects.nonNull(item.getEnable()) && Objects.equals(item.getEnable(), EnableEnum.OPEN.getCode())).collect(Collectors.toList());
        Map<Long, PaasStageEntity> paasStageEntityMap = enableStageEntityList.stream().collect(Collectors.toMap(PaasStageEntity::getId, t -> t, (t, t1) -> t1));
        paasStageEntityMap.put(firstStageEntity.getId(), firstStageEntity);
        Map<Integer, List<PaasStageEntity>> stageMap = abstractStageSettingsStrategy.getStageMap(new ArrayList<>(paasStageEntityMap.values()));
        List<PaasStageEntity> paasStageEntities = stageMap.get(firstStageEntity.getType());
        abstractStageSettingsStrategy.stageNormalCheck(businessType, Collections.singletonList(firstStageEntity));
        stageSettingsStrategy.check(paasStageEntities, businessType);
        // 校验阶段任务
        List<StageWorkEntity> stageWorkEntityList = stageHelp.getStageWorkEntityByProcess(corpid, formId, firstStageEntity.getStageProcessId());
        Map<Long, List<StageWorkEntity>> stageWorkEntityMap = stageWorkEntityList.stream().collect(Collectors.groupingBy(StageWorkEntity::getStageId));
        for (PaasStageEntity stageEntity : paasStageEntities) {
            stageSettingsStrategy.checkStageWork(stageEntity, stageWorkEntityMap.get(stageEntity.getId()));
        }
        Map<Long, PaasStageEntity> changeEntityMap = paasStageEntities.stream().collect(Collectors.toMap(PaasStageEntity::getId, t -> t, (t, t1) -> t1));
        Map<Long, PaasStageEntity> stageEntityMap = stageEntityList.stream().collect(Collectors.toMap(PaasStageEntity::getId, t -> t, (t, t1) -> t1));
        stageEntityMap.putAll(changeEntityMap);
        stageEntityList = new ArrayList<>(stageEntityMap.values());
        Map<Long, PaasStageEntity> oldStageMap = new HashMap<>(stageEntityList.size());
        stageEntityList.forEach(item -> {
            oldStageMap.put(item.getId(), item);
            String code = UUID.randomUUID().toString();
            code = code.replace("-", "");
            item.setId(null);
            item.setStageProcessId(processEntityId);
            item.setCode(code);
            item.setUpdateTime(DateTimeUtil.getInt());
            item.setAddTime(DateTimeUtil.getInt());
        });
        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        stageHandle.insertBatch(stageEntityList);

        //新建结束后置动作
        List<PaasStageEntity> updateStageEntityList = getUpdateStageEntity(stageEntityList, oldStageMap);
        if (CollectionsUtil.isNotEmpty(updateStageEntityList)) {
            stageHandle.updateBatch(stageEntityList, corpid);
        }

        //复制阶段任务
        copyStageWork(stageWorkEntityList, oldStageMap);

        //记录日志
        abstractStageSettingsStrategy.saveStageProcessLog(stageSaveDTO, formId, null, Collections.singletonList(stageProcessEntity));
        stageProcessArchiveVO.setId(stageProcessEntity.getId());
        return stageProcessArchiveVO;
    }

    /**
     * 复制和排序阶段任务
     * @param stageWorkSortDTO
     * @return
     * @throws XbbException
     */
    public StageProcessArchiveVO copyAndSortStageWork(StageWorkSortDTO stageWorkSortDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();
        String corpid = stageWorkSortDTO.getCorpid();
        Long stageId = stageWorkSortDTO.getStageId();
        Integer businessType = stageWorkSortDTO.getBusinessType();
        Integer saasMark = stageWorkSortDTO.getSaasMark();
        List<SortPojo> sortList = stageWorkSortDTO.getSortList();

        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        PaasStageEntity paasStageEntity = stageHandle.getByKey(stageId, corpid);

        if (Objects.isNull(paasStageEntity) || Objects.equals(paasStageEntity.getDel(), DelEnum.DELETE.getDel())) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238019);
        }
        Long stageProcessId = paasStageEntity.getStageProcessId();
        Long formId = paasStageEntity.getFormId();

        // 复制阶段流程
        StageProcessEntity stageProcessEntity = getCopyStageProcess(corpid, formId, stageProcessId);
        stageProcessModel.insert(stageProcessEntity);

        //复制阶段
        List<PaasStageEntity> stageEntityList = stageHelp.getStageEntitys(corpid, saasMark, businessType, formId, stageProcessId);
        if (CollectionsUtil.isEmpty(stageEntityList)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238016);
        }
        Map<Long, PaasStageEntity> oldStageMap = new HashMap<>(stageEntityList.size());
        stageEntityList.forEach(item -> {
            oldStageMap.put(item.getId(), item);
            String code = UUID.randomUUID().toString();
            code = code.replace("-", "");
            item.setId(null);
            item.setStageProcessId(stageProcessEntity.getId());
            item.setCode(code);
            item.setUpdateTime(DateTimeUtil.getInt());
            item.setAddTime(DateTimeUtil.getInt());
        });
        stageHandle.insertBatch(stageEntityList);

        //复制工作流
        List<StageWorkflowEntity> stageWorkflowEntityList = stageHelp.getStageWorkflowEntity(corpid, formId, stageProcessId);
        for (StageWorkflowEntity stageWorkflowEntity : stageWorkflowEntityList) {
            PaasStageEntity newPaasStageEntity = oldStageMap.get(stageWorkflowEntity.getStageId());
            PaasStageEntity newRelatedStageEntity = oldStageMap.get(stageWorkflowEntity.getRelatedStageId());
            if (Objects.nonNull(newPaasStageEntity) && Objects.nonNull(newRelatedStageEntity)) {
                long now = DateTimeUtil.getInt();
                stageWorkflowEntity.setId(null);
                stageWorkflowEntity.setStageProcessId(newPaasStageEntity.getStageProcessId());
                stageWorkflowEntity.setStageId(newPaasStageEntity.getId());
                stageWorkflowEntity.setRelatedStageId(newRelatedStageEntity.getId());
                stageWorkflowEntity.setAddTime(now);
                stageWorkflowEntity.setUpdateTime(now);
            }
        }
        stageWorkflowModel.insertBatch(stageWorkflowEntityList);

        //新建结束后置动作
        List<PaasStageEntity> updateStageEntityList = getUpdateStageEntity(stageEntityList, oldStageMap);
        if (CollectionsUtil.isNotEmpty(updateStageEntityList)) {
            stageHandle.updateBatch(stageEntityList, corpid);
        }

        //复制阶段任务
        List<StageWorkEntity> stageWorkEntityList = stageHelp.getStageWorkEntityByProcess(corpid, formId, stageProcessId);
        Map<Long, Integer> sortMap = sortList.stream().collect(Collectors.toMap(SortPojo::getId, SortPojo::getSort));
        for (StageWorkEntity stageWorkEntity : stageWorkEntityList) {
            Integer sort = sortMap.get(stageWorkEntity.getId());
            if (Objects.nonNull(sort)) {
                stageWorkEntity.setSort(sort);
            }
        }
        copyStageWork(stageWorkEntityList, oldStageMap);
        //记录日志
        abstractStageSettingsStrategy.saveStageProcessLog(stageWorkSortDTO, formId, null, Collections.singletonList(stageProcessEntity));
        stageProcessArchiveVO.setId(stageProcessEntity.getId());
        return stageProcessArchiveVO;
    }

    /**
     * 复制和删除阶段任务
     * @param stageWorkGetDTO
     * @return
     * @throws XbbException
     */
    public StageProcessArchiveVO copyAndDelStageWork(StageWorkGetDTO stageWorkGetDTO) throws XbbException {

        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();
        String corpid = stageWorkGetDTO.getCorpid();
        Long id = stageWorkGetDTO.getId();
        Integer businessType = stageWorkGetDTO.getBusinessType();

        StageWorkEntity stageWorkEntity = stageWorkModel.getByKey(id, corpid);
        if (Objects.isNull(stageWorkEntity) || Objects.equals(stageWorkEntity.getDel(), DelEnum.DELETE.getDel())) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238020);
        }
        Long stageProcessId = stageWorkEntity.getStageProcessId();
        Long formId = stageWorkEntity.getFormId();
        Integer saasMark = stageWorkEntity.getSaasMark();

        // 复制阶段流程
        StageProcessEntity stageProcessEntity = getCopyStageProcess(corpid, formId, stageProcessId);
        stageProcessModel.insert(stageProcessEntity);

        //复制阶段
        List<PaasStageEntity> stageEntityList = stageHelp.getStageEntitys(corpid, saasMark, businessType, formId, stageProcessId);
        if (CollectionsUtil.isEmpty(stageEntityList)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238016);
        }
        Map<Long, PaasStageEntity> oldStageMap = new HashMap<>(stageEntityList.size());
        stageEntityList.forEach(item -> {
            oldStageMap.put(item.getId(), item);
            String code = UUID.randomUUID().toString();
            code = code.replace("-", "");
            item.setId(null);
            item.setStageProcessId(stageProcessEntity.getId());
            item.setCode(code);
            item.setUpdateTime(DateTimeUtil.getInt());
            item.setAddTime(DateTimeUtil.getInt());
        });
        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        stageHandle.insertBatch(stageEntityList);

        //复制工作流
        List<StageWorkflowEntity> stageWorkflowEntityList = stageHelp.getStageWorkflowEntity(corpid, formId, id);
        for (StageWorkflowEntity stageWorkflowEntity : stageWorkflowEntityList) {
            PaasStageEntity newPaasStageEntity = oldStageMap.get(stageWorkflowEntity.getStageId());
            PaasStageEntity newRelatedStageEntity = oldStageMap.get(stageWorkflowEntity.getRelatedStageId());
            if (Objects.nonNull(newPaasStageEntity) && Objects.nonNull(newRelatedStageEntity)) {
                long now = DateTimeUtil.getInt();
                stageWorkflowEntity.setId(null);
                stageWorkflowEntity.setStageProcessId(newPaasStageEntity.getStageProcessId());
                stageWorkflowEntity.setStageId(newPaasStageEntity.getId());
                stageWorkflowEntity.setRelatedStageId(newRelatedStageEntity.getId());
                stageWorkflowEntity.setAddTime(now);
                stageWorkflowEntity.setUpdateTime(now);
            }
        }
        stageWorkflowModel.insertBatch(stageWorkflowEntityList);

        //新建结束后置动作
        List<PaasStageEntity> updateStageEntityList = getUpdateStageEntity(stageEntityList, oldStageMap);
        if (CollectionsUtil.isNotEmpty(updateStageEntityList)) {
            stageHandle.updateBatch(stageEntityList, corpid);
        }
        //复制阶段任务
        List<StageWorkEntity> stageWorkEntityList = stageHelp.getStageWorkEntityByProcess(corpid, formId, stageProcessId);
        Map<Long, StageWorkEntity> stageWorkEntityMap = stageWorkEntityList.stream().collect(Collectors.toMap(StageWorkEntity::getId, t -> t, (t, t1) -> t1));
        stageWorkEntityMap.remove(id);
        copyStageWork(new ArrayList<>(stageWorkEntityMap.values()), oldStageMap);

        //记录日志
        abstractStageSettingsStrategy.saveStageProcessLog(stageWorkGetDTO, formId, null, Collections.singletonList(stageProcessEntity));
        stageProcessArchiveVO.setId(stageProcessEntity.getId());
        return stageProcessArchiveVO;
    }

    /**
     * 复制和修改阶段任务
     * @param stageWorkSaveDTO
     * @return
     * @throws XbbException
     */
    public StageProcessArchiveVO copyAndSaveStageWork(StageWorkSaveDTO stageWorkSaveDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();
        Long id = stageWorkSaveDTO.getId();
        String corpid = stageWorkSaveDTO.getCorpid();
        Long formId = stageWorkSaveDTO.getFormId();
        Integer saasMark = stageWorkSaveDTO.getSaasMark();
        Integer businessType = stageWorkSaveDTO.getBusinessType();
        Long stageId = stageWorkSaveDTO.getStageId();
        StageWorkPojo stageWorkPojo = stageWorkSaveDTO.getStageWorkPojo();
        stageWorkPojo.setId(id);
        StageWorkEntity stageWorkEntity;

        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        PaasStageEntity stageEntity = stageHandle.getByKey(stageId, corpid);
        if (Objects.isNull(stageEntity)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238019);
        }
        Long stageProcessId = stageEntity.getStageProcessId();

        // 复制阶段流程
        StageProcessEntity stageProcessEntity = getCopyStageProcess(corpid, formId, stageProcessId);
        stageProcessModel.insert(stageProcessEntity);

        //复制阶段
        List<PaasStageEntity> stageEntityList = stageHelp.getStageEntitys(corpid, saasMark, businessType, formId, stageProcessId);
        if (CollectionsUtil.isEmpty(stageEntityList)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238016);
        }
        Map<Long, PaasStageEntity> oldStageMap = new HashMap<>(stageEntityList.size());
        stageEntityList.forEach(item -> {
            oldStageMap.put(item.getId(), item);
            String code = UUID.randomUUID().toString();
            code = code.replace("-", "");
            item.setId(null);
            item.setStageProcessId(stageProcessEntity.getId());
            item.setCode(code);
            item.setUpdateTime(DateTimeUtil.getInt());
            item.setAddTime(DateTimeUtil.getInt());
        });
        stageHandle.insertBatch(stageEntityList);

        //复制工作流
        List<StageWorkflowEntity> stageWorkflowEntityList = stageHelp.getStageWorkflowEntity(corpid, formId, id);
        for (StageWorkflowEntity stageWorkflowEntity : stageWorkflowEntityList) {
            PaasStageEntity newPaasStageEntity = oldStageMap.get(stageWorkflowEntity.getStageId());
            PaasStageEntity newRelatedStageEntity = oldStageMap.get(stageWorkflowEntity.getRelatedStageId());
            if (Objects.nonNull(newPaasStageEntity) && Objects.nonNull(newRelatedStageEntity)) {
                long now = DateTimeUtil.getInt();
                stageWorkflowEntity.setId(null);
                stageWorkflowEntity.setStageProcessId(newPaasStageEntity.getStageProcessId());
                stageWorkflowEntity.setStageId(newPaasStageEntity.getId());
                stageWorkflowEntity.setRelatedStageId(newRelatedStageEntity.getId());
                stageWorkflowEntity.setAddTime(now);
                stageWorkflowEntity.setUpdateTime(now);
            }
        }
        if (CollectionsUtil.isNotEmpty(stageWorkflowEntityList)) {
            stageWorkflowModel.insertBatch(stageWorkflowEntityList);
        }

        //新建结束后置动作
        List<PaasStageEntity> updateStageEntityList = getUpdateStageEntity(stageEntityList, oldStageMap);
        if (CollectionsUtil.isNotEmpty(updateStageEntityList)) {
            stageHandle.updateBatch(stageEntityList, corpid);
        }

        //校验阶段任务
        List<StageWorkEntity> stageWorkEntityByProcess = stageHelp.getStageWorkEntityByProcess(corpid, formId, stageProcessId);
        Map<Long, List<StageWorkEntity>> stageWorkListMap = stageWorkEntityByProcess.stream().collect(Collectors.groupingBy(StageWorkEntity::getStageId));
        List<StageWorkEntity> stageWorkEntityList = stageWorkListMap.get(stageId);
        if (Objects.isNull(stageWorkEntityList)) {
            stageWorkEntityList = new ArrayList<>();
        }
        Map<Long, StageWorkEntity> stageWorkEntityMap = stageWorkEntityList.stream().collect(Collectors.toMap(StageWorkEntity::getId, Function.identity(), (t, t1) -> t1));
        Integer stageBusinessType = stageHelp.getStageBusinessType(businessType);
        if (Objects.isNull(id)) {
            stageWorkEntity = new StageWorkEntity();
            stageWorkEntity.setCorpid(corpid);
            stageWorkEntity.setFormId(formId);
            stageWorkEntity.setStageProcessId(stageEntity.getStageProcessId());
            stageWorkEntity.setStageId(stageEntity.getId());
            stageWorkEntity.setStageCode(stageEntity.getCode());
            stageWorkEntity.setBusinessType(stageBusinessType);
            stageWorkEntity.setSaasMark(saasMark);
            stageWorkEntity.setAddTime(DateTimeUtil.getInt());
            stageHelp.wrapStageWorkEntity(stageWorkEntity, stageWorkPojo);

            stageWorkEntityList.add(stageWorkEntity);
            StageSettingsStrategy stageSettingsStrategy = stageSettingsFactory.getStageSettingsStrategy(stageEntity.getType());
            stageSettingsStrategy.checkStageWork(stageEntity, stageWorkEntityList);
            stageWorkEntityMap.put(stageWorkEntity.getId(), stageWorkEntity);
        } else {
            stageWorkEntity = stageWorkEntityMap.get(id);
            if (Objects.isNull(stageWorkEntity)) {
                throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238020);
            }
            stageHelp.wrapStageWorkEntity(stageWorkEntity, stageWorkPojo);
            stageWorkEntityList = new ArrayList<>(stageWorkEntityMap.values());
            abstractStageSettingsStrategy.checkStageWork(stageEntity, stageWorkEntityList);
        }

        //复制阶段任务
        Map<Long, StageWorkEntity> allStageWorkEntityMap = stageWorkEntityByProcess.stream().collect(Collectors.toMap(StageWorkEntity::getId, Function.identity(), (t, t1) -> t1));
        allStageWorkEntityMap.putAll(stageWorkEntityMap);
        copyStageWork(new ArrayList<>(allStageWorkEntityMap.values()), oldStageMap);

        //记录日志
        abstractStageSettingsStrategy.saveStageProcessLog(stageWorkSaveDTO, formId, null, Collections.singletonList(stageProcessEntity));
        stageProcessArchiveVO.setId(stageProcessEntity.getId());
        return stageProcessArchiveVO;
    }

    /**
     * 复制和保存阶段
     * @param stageSaveDTO
     * @return
     * @throws XbbException
     */
    public StageProcessArchiveVO copyAndSaveStage(StageSaveDTO stageSaveDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();

        Long id = stageSaveDTO.getId();
        String corpid = stageSaveDTO.getCorpid();
        Long formId = stageSaveDTO.getFormId();
        Long stageProcessId = stageSaveDTO.getStageProcessId();
        Integer saasMark = stageSaveDTO.getSaasMark();
        Integer businessType = stageSaveDTO.getBusinessType();
        StageSavePojo stageSavePojo = stageSaveDTO.getStageSavePojo();
        stageSavePojo.setId(id);
        Integer type = stageSavePojo.getType();

        // 复制阶段流程
        StageProcessEntity stageProcessEntity = getCopyStageProcess(corpid, formId, stageProcessId);
        stageProcessModel.insert(stageProcessEntity);

        //复制阶段
        Long processEntityId = stageProcessEntity.getId();
        List<PaasStageEntity> stageEntityList = stageHelp.getStageEntitys(corpid, saasMark, businessType, formId, stageProcessId);
        if (CollectionsUtil.isEmpty(stageEntityList)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238016);
        }
        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        PaasStageEntity paasStageEntity = stageHandle.getByKey(id, corpid);
        if (Objects.isNull(paasStageEntity)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238019);
        }

        //校验阶段
        StageSettingsStrategy stageSettingsStrategy = stageSettingsFactory.getStageSettingsStrategy(type);
        List<PaasStageEntity> enableStageEntityList = stageEntityList.stream().filter(item -> Objects.nonNull(item.getEnable()) && Objects.equals(item.getEnable(), EnableEnum.OPEN.getCode())).collect(Collectors.toList());
        Map<Long, PaasStageEntity> paasStageEntityMap = enableStageEntityList.stream().collect(Collectors.toMap(PaasStageEntity::getId, t -> t, (t, t1) -> t1));
        PaasStageEntity saveStageEntity = stageHelp.wrapStageEntity(paasStageEntity, stageSavePojo);
        paasStageEntityMap.put(saveStageEntity.getId(), saveStageEntity);
        Map<Integer, List<PaasStageEntity>> stageMap = abstractStageSettingsStrategy.getStageMap(new ArrayList<>(paasStageEntityMap.values()));
        List<PaasStageEntity> paasStageEntities = stageMap.get(type);
        abstractStageSettingsStrategy.stageNormalCheck(businessType, Collections.singletonList(saveStageEntity));
        stageSettingsStrategy.check(paasStageEntities, businessType);
        // 校验阶段任务
        List<StageWorkEntity> stageWorkEntityList = stageHelp.getStageWorkEntityByProcess(corpid, formId, paasStageEntity.getStageProcessId());
        Map<Long, List<StageWorkEntity>> stageWorkEntityMap = stageWorkEntityList.stream().collect(Collectors.groupingBy(StageWorkEntity::getStageId));
        for (PaasStageEntity stageEntity : paasStageEntities) {
            stageSettingsStrategy.checkStageWork(stageEntity, stageWorkEntityMap.get(stageEntity.getId()));
        }
        Map<Long, PaasStageEntity> changeEntityMap = paasStageEntities.stream().collect(Collectors.toMap(PaasStageEntity::getId, t -> t, (t, t1) -> t1));
        Map<Long, PaasStageEntity> stageEntityMap = stageEntityList.stream().collect(Collectors.toMap(PaasStageEntity::getId, t -> t, (t, t1) -> t1));
        stageEntityMap.putAll(changeEntityMap);
        stageEntityList = new ArrayList<>(stageEntityMap.values());
        Map<Long, PaasStageEntity> oldStageMap = new HashMap<>(stageEntityList.size());
        stageEntityList.forEach(item -> {
            oldStageMap.put(item.getId(), item);
            String code = UUID.randomUUID().toString();
            code = code.replace("-", "");
            item.setId(null);
            item.setStageProcessId(processEntityId);
            item.setCode(code);
            item.setUpdateTime(DateTimeUtil.getInt());
            item.setAddTime(DateTimeUtil.getInt());
        });
        stageHandle.insertBatch(stageEntityList);

        //复制工作流
        List<StageWorkflowEntity> stageWorkflowEntityList = stageHelp.getStageWorkflowEntity(corpid, formId, id);
        for (StageWorkflowEntity stageWorkflowEntity : stageWorkflowEntityList) {
            PaasStageEntity newPaasStageEntity = oldStageMap.get(stageWorkflowEntity.getStageId());
            PaasStageEntity newRelatedStageEntity = oldStageMap.get(stageWorkflowEntity.getRelatedStageId());
            if (Objects.nonNull(newPaasStageEntity) && Objects.nonNull(newRelatedStageEntity)) {
                long now = DateTimeUtil.getInt();
                stageWorkflowEntity.setId(null);
                stageWorkflowEntity.setStageProcessId(newPaasStageEntity.getStageProcessId());
                stageWorkflowEntity.setStageId(newPaasStageEntity.getId());
                stageWorkflowEntity.setRelatedStageId(newRelatedStageEntity.getId());
                stageWorkflowEntity.setAddTime(now);
                stageWorkflowEntity.setUpdateTime(now);
            }
        }
        stageWorkflowModel.insertBatch(stageWorkflowEntityList);

        //新建结束后置动作
        List<PaasStageEntity> updateStageEntityList = getUpdateStageEntity(stageEntityList, oldStageMap);
        if (CollectionsUtil.isNotEmpty(updateStageEntityList)) {
            stageHandle.updateBatch(stageEntityList, corpid);
        }

        //复制阶段任务
        copyStageWork(stageWorkEntityList, oldStageMap);

        //记录日志
        abstractStageSettingsStrategy.saveStageProcessLog(stageSaveDTO, formId, null, Collections.singletonList(stageProcessEntity));
        stageProcessArchiveVO.setId(stageProcessEntity.getId());
        return stageProcessArchiveVO;
    }

    /**
     * 复制并修改阶段流程
     * @param stageProcessSaveDTO
     * @return
     * @throws XbbException
     */
    public StageProcessArchiveVO copyAndSaveStageProcess(StageProcessSaveDTO stageProcessSaveDTO) throws XbbException {
        StageProcessArchiveVO stageProcessArchiveVO = new StageProcessArchiveVO();

        String corpid = stageProcessSaveDTO.getCorpid();
        Long formId = stageProcessSaveDTO.getFormId();
        Long id = stageProcessSaveDTO.getId();
        Integer saasMark = stageProcessSaveDTO.getSaasMark();
        Integer businessType = stageProcessSaveDTO.getBusinessType();
        List<StageSavePojo> stageSavePojoList = stageProcessSaveDTO.getStageList();

        if (CollectionsUtil.isEmpty(stageSavePojoList) || stageSavePojoList.size() < BasicConstant.THREE) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238016);
        }
        //去除机会业务类型的限制，扩展客户、线索、paas阶段表单
        if (Objects.isNull(businessType)) {
            throw new XbbException(BusinessTypeErrorCodeEnum.API_ERROR_361001);
        }
        //复制流程
        StageProcessEntity stageProcessEntity = getCopyStageProcess(corpid, formId, id);
        getStageProcessEntity4Opportunity(stageProcessEntity, stageProcessSaveDTO);
        stageProcessModel.insert(stageProcessEntity);

        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);

        //复制阶段
        Long processEntityId = stageProcessEntity.getId();
        List<PaasStageEntity> stageEntityList = getPaasStageEntity4Copy(corpid, formId, processEntityId, stageSavePojoList, stageHandle);
        if (CollectionsUtil.isEmpty(stageEntityList)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238016);
        }
        Map<Long, PaasStageEntity> oldStageMap = new HashMap<>(stageEntityList.size());
        stageEntityList.forEach(item -> {
            oldStageMap.put(item.getId(), item);
            String code = UUID.randomUUID().toString();
            code = code.replace("-", "");
            item.setId(null);
            item.setStageProcessId(processEntityId);
            item.setCode(code);
            item.setUpdateTime(DateTimeUtil.getInt());
            item.setAddTime(DateTimeUtil.getInt());
        });
        // 校验阶段
        List<PaasStageEntity> enableStageList = stageEntityList.stream()
                .filter(item ->
                        Objects.nonNull(item.getEnable()) &&
                                Objects.equals(item.getEnable(), EnableEnum.OPEN.getCode()))
                .collect(Collectors.toList());
        List<PaasStageEntity> closeStageList = stageEntityList.stream()
                .filter(item ->
                        Objects.nonNull(item.getEnable()) &&
                                Objects.equals(item.getEnable(), EnableEnum.CLOSE.getCode()) &&
                                Objects.isNull(item.getIntoProportion()))
                .collect(Collectors.toList());
        closeStageList.forEach(item -> item.setIntoProportion(item.getOutProportion()));
        checkStage(enableStageList, businessType);
        stageHandle.insertBatch(stageEntityList);

        //新建结束后置动作
        List<PaasStageEntity> updateStageEntityList = getUpdateStageEntity(stageEntityList, oldStageMap);
        if (CollectionsUtil.isNotEmpty(updateStageEntityList)) {
            stageHandle.updateBatch(stageEntityList, corpid);
        }

        //复制工作流
        List<StageWorkflowEntity> stageWorkflowEntityList = stageHelp.getStageWorkflowEntity(corpid, formId, id);
        for (StageWorkflowEntity stageWorkflowEntity : stageWorkflowEntityList) {
            PaasStageEntity newPaasStageEntity = oldStageMap.get(stageWorkflowEntity.getStageId());
            PaasStageEntity newRelatedStageEntity = oldStageMap.get(stageWorkflowEntity.getRelatedStageId());
            if (Objects.nonNull(newPaasStageEntity) && Objects.nonNull(newRelatedStageEntity)) {
                long now = DateTimeUtil.getInt();
                stageWorkflowEntity.setId(null);
                stageWorkflowEntity.setStageProcessId(newPaasStageEntity.getStageProcessId());
                stageWorkflowEntity.setStageId(newPaasStageEntity.getId());
                stageWorkflowEntity.setRelatedStageId(newRelatedStageEntity.getId());
                stageWorkflowEntity.setAddTime(now);
                stageWorkflowEntity.setUpdateTime(now);
            }
        }
        //fix:49157 【阶段推进器】修改阶段生成新版本。提示网络请求失败
        if (CollectionsUtil.isNotEmpty(stageWorkflowEntityList)) {
            stageWorkflowModel.insertBatch(stageWorkflowEntityList);
        }

        //复制阶段任务
        List<StageWorkEntity> stageWorkEntityList = stageHelp.getStageWorkEntityByProcess(corpid, formId, id);
        copyStageWork(stageWorkEntityList, oldStageMap);

        //记录日志
        abstractStageSettingsStrategy.saveStageProcessLog(stageProcessSaveDTO, formId, null, Collections.singletonList(stageProcessEntity));
        stageProcessArchiveVO.setId(stageProcessEntity.getId());
        return stageProcessArchiveVO;
    }

    /**
     * 获取需复制流程的实体
     * @param corpid
     * @param formId
     * @param id
     * @return
     * @throws XbbException
     */
    private StageProcessEntity getCopyStageProcess(String corpid, Long formId, Long id) throws XbbException {
        //复制流程
        StageProcessEntity stageProcessEntity = stageProcessModel.getByKey(id, corpid);
        if (Objects.isNull(stageProcessEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.STAGE_PROCESS_NOT_EXIST);
        }
        List<StageProcessEntity> processEntityList = stageHelp.getStageProcessList(corpid, formId);
        //阶段流程不管归档与未归档 最多只能存在30条
        if (CollectionsUtil.isNotEmpty(processEntityList) && processEntityList.size() >= StageProcessConstant.STAGE_PROCESS_MAX_COUNT) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, String.format(I18nMessageUtil.getMessage(MessageConstant.STAGE_PROCESS_MAX_NUM), StageProcessConstant.STAGE_PROCESS_MAX_COUNT));
        }
        // 将当前新建的阶段流程设置为最新版本
        int versionId = 1;
        int priority = 1;
        if (CollectionsUtil.isNotEmpty(processEntityList)) {
            versionId = processEntityList.get(0).getVersionId() + 1;
            processEntityList = processEntityList.stream().sorted(Comparator.comparing(StageProcessEntity::getPriority).reversed()).collect(Collectors.toList());
            priority = processEntityList.get(0).getPriority() + 1;
        }
        Long now = DateTimeUtil.getInt();
        stageProcessEntity.setId(null);
        stageProcessEntity.setAddTime(now);
        stageProcessEntity.setUpdateTime(now);
        stageProcessEntity.setEnable(EnableEnum.CLOSE.getCode());
        stageProcessEntity.setVersionId(versionId);
        stageProcessEntity.setVersionName("v" + versionId);
        stageProcessEntity.setOldTransferVersion(BasicConstant.ZERO);
        stageProcessEntity.setPriority(priority);
        return stageProcessEntity;
    }


    /**
     * 保存阶段列表
     * @param corpid
     * @param saasMark
     * @param businessType
     * @param formId
     * @param stageProcessId
     * @param paasStageEntityList
     * @throws XbbException
     */
    private void saveStage(String corpid, Integer saasMark,  Integer businessType, Long formId, Long stageProcessId, List<PaasStageEntity> paasStageEntityList) throws XbbException {
        if (CollectionsUtil.isEmpty(paasStageEntityList)) {
            return;
        }
        //校验阶段-只校验已启用的阶段
        List<PaasStageEntity> enableStageList = paasStageEntityList.stream().filter(item -> Objects.nonNull(item.getEnable()) && Objects.equals(item.getEnable(), EnableEnum.OPEN.getCode())).collect(Collectors.toList());
        List<PaasStageEntity> closeStageList = paasStageEntityList.stream().filter(item -> Objects.nonNull(item.getEnable()) && Objects.equals(item.getEnable(), EnableEnum.CLOSE.getCode()) && Objects.isNull(item.getIntoProportion())).collect(Collectors.toList());
        closeStageList.forEach(item -> item.setIntoProportion(item.getOutProportion()));
        checkStage(enableStageList, businessType);
        // 校验阶段任务
        List<StageWorkEntity> stageWorkEntityList = stageHelp.getStageWorkEntityByProcess(corpid, formId, stageProcessId);
        Map<Long, List<StageWorkEntity>> stageWorkEntityMap = stageWorkEntityList.stream().collect(Collectors.groupingBy(StageWorkEntity::getStageId));
        for (PaasStageEntity stageEntity : enableStageList) {
            abstractStageSettingsStrategy.checkStageWork(stageEntity, stageWorkEntityMap.get(stageEntity.getId()));
        }

        List<PaasStageEntity> insertStageList = paasStageEntityList.stream().filter(item -> Objects.isNull(item.getId())).collect(Collectors.toList());
        List<PaasStageEntity> updateStageList = paasStageEntityList.stream().filter(item -> Objects.nonNull(item.getId())).collect(Collectors.toList());
        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        if (CollectionsUtil.isNotEmpty(insertStageList)) {
            insertStageList.forEach(item -> item.setAddTime(DateTimeUtil.getInt()));
            stageHandle.insertBatch(insertStageList);
        }
        if (CollectionsUtil.isNotEmpty(updateStageList)) {
            saleStageModifyLogModel.saveModifyLogWhenUpdateStage(corpid, formId, stageProcessId, businessType, updateStageList);
            stageHandle.updateBatch(updateStageList, corpid);
        }
    }

    /**
     * 校验阶段
     * @param paasStageEntityList
     * @throws XbbException
     */
    private void checkStage(List<PaasStageEntity> paasStageEntityList, Integer businessType) throws XbbException {
        List<Integer> notStartTypeList = StageTypeEnum.getNotStartType();
        Map<Integer, List<PaasStageEntity>> stageMap = abstractStageSettingsStrategy.getStageMap(paasStageEntityList);
        if (Objects.isNull(stageMap)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238016);
        }
        for (Integer stageType : notStartTypeList) {
            StageSettingsStrategy stageSettingsStrategy = stageSettingsFactory.getStageSettingsStrategy(stageType);
            stageSettingsStrategy.check(stageMap.get(stageType), businessType);
        }
    }

    /**
     * 封装阶段流程实体
     * @param stageProcessSaveDTO
     * @return
     */
    private StageProcessEntity getStageProcessEntity(StageProcessSaveDTO stageProcessSaveDTO) {
        StageProcessEntity stageProcessEntity = new StageProcessEntity();
        stageProcessEntity.setCorpid(stageProcessSaveDTO.getCorpid());
        stageProcessEntity.setFormId(stageProcessSaveDTO.getFormId());
        stageProcessEntity.setName(stageProcessSaveDTO.getName());
        stageProcessEntity.setVersionName(stageProcessSaveDTO.getVersionName());
        stageProcessEntity.setVersionId(stageProcessSaveDTO.getVersionId());
        stageProcessEntity.setEnable(stageProcessSaveDTO.getEnable());
        stageProcessEntity.setStageUnit(stageProcessSaveDTO.getStageUnit());
        stageProcessEntity.setAllowBack(stageProcessSaveDTO.getAllowBack());
        stageProcessEntity.setAllowNewSelect(stageProcessSaveDTO.getAllowNewSelect());
        JSONArray allowNewSelectUser = Objects.isNull(stageProcessSaveDTO.getAllowNewSelectUser()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageProcessSaveDTO.getAllowNewSelectUser()));
        stageProcessEntity.setAllowNewSelectUser(allowNewSelectUser);
        stageProcessEntity.setShowTimeUse(stageProcessSaveDTO.getShowTimeUse());
        stageProcessEntity.setShowTimeStay(stageProcessSaveDTO.getShowTimeStay());
        stageProcessEntity.setShowWorkCompletion(stageProcessSaveDTO.getShowWorkCompletion());
        stageProcessEntity.setShowAverageCompletionTime(stageProcessSaveDTO.getShowAverageCompletionTime());
        JSONArray triggerCondition = Objects.isNull(stageProcessSaveDTO.getTriggerCondition()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageProcessSaveDTO.getTriggerCondition()));
        stageProcessEntity.setTriggerCondition(triggerCondition);
        stageProcessEntity.setIsArchive(ArchivedEnum.UN_ARCHIVED.getCode());
        stageProcessEntity.setDel(DelEnum.NORMAL.getDel());
        stageProcessEntity.setPriority(Objects.isNull(stageProcessSaveDTO.getPriority()) ? 1 : stageProcessSaveDTO.getPriority());
        return stageProcessEntity;
    }

    /**
     * 获取阶段流程实体-机会生成新版本
     * @param stageProcessEntity
     * @param stageProcessSaveDTO
     * @return
     */
    private StageProcessEntity getStageProcessEntity4Opportunity(StageProcessEntity stageProcessEntity, StageProcessSaveDTO stageProcessSaveDTO) {
        stageProcessEntity.setEnable(EnableEnum.CLOSE.getCode());
        stageProcessEntity.setStageUnit(stageProcessSaveDTO.getStageUnit());
        stageProcessEntity.setAllowBack(stageProcessSaveDTO.getAllowBack());
        stageProcessEntity.setAllowNewSelect(stageProcessSaveDTO.getAllowNewSelect());
        JSONArray allowNewSelectUser = Objects.isNull(stageProcessSaveDTO.getAllowNewSelectUser()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageProcessSaveDTO.getAllowNewSelectUser()));
        stageProcessEntity.setAllowNewSelectUser(allowNewSelectUser);
        stageProcessEntity.setShowTimeUse(stageProcessSaveDTO.getShowTimeUse());
        stageProcessEntity.setShowTimeStay(stageProcessSaveDTO.getShowTimeStay());
        stageProcessEntity.setShowWorkCompletion(stageProcessSaveDTO.getShowWorkCompletion());
        stageProcessEntity.setShowAverageCompletionTime(stageProcessSaveDTO.getShowAverageCompletionTime());
        JSONArray triggerCondition = Objects.isNull(stageProcessSaveDTO.getTriggerCondition()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageProcessSaveDTO.getTriggerCondition()));
        stageProcessEntity.setTriggerCondition(triggerCondition);
        stageProcessEntity.setIsArchive(ArchivedEnum.UN_ARCHIVED.getCode());
        stageProcessEntity.setDel(DelEnum.NORMAL.getDel());
        return stageProcessEntity;
    }

    /**
     * 封装阶段实体
     * @param corpid
     * @param formId
     * @param stageProcessId
     * @param stageSavePojoList
     * @param stageHandle
     * @return
     */
    public List<PaasStageEntity> getPaasStageEntity(String corpid, Long formId, Long stageProcessId, List<StageSavePojo> stageSavePojoList, StageHandle stageHandle) {
        if (CollectionsUtil.isEmpty(stageSavePojoList)) {
            return new ArrayList<>();
        }
        List<PaasStageEntity> paasStageEntityList = new ArrayList<>(stageSavePojoList.size());
        for (StageSavePojo stageSavePojo : stageSavePojoList) {
            PaasStageEntity paasStageEntity = new PaasStageEntity();
            paasStageEntity.setCorpid(corpid);
            paasStageEntity.setFormId(formId);
            paasStageEntity.setStageProcessId(stageProcessId);
            paasStageEntity.setName(stageSavePojo.getName());
            paasStageEntity.setCode(stageSavePojo.getCode());
            paasStageEntity.setIntoProportion(stageSavePojo.getIntoProportion());
            paasStageEntity.setOutProportion(stageSavePojo.getOutProportion());
            paasStageEntity.setType(stageSavePojo.getType());
            paasStageEntity.setEnable(stageSavePojo.getEnable());
            paasStageEntity.setSort(stageSavePojo.getSort());
            Integer stayLimit = Objects.isNull(stageSavePojo.getStayLimit()) ? 0 : stageSavePojo.getStayLimit();
            paasStageEntity.setStayLimit(stayLimit);
            paasStageEntity.setStayLimitTime(stageSavePojo.getStayLimitTime());
            paasStageEntity.setStayLimitTimeUnit(stageSavePojo.getStayLimitTimeUnit());
            paasStageEntity.setEnableStageWarningColor(Objects.isNull(stageSavePojo.getEnableStageWarningColor()) ? 0 : stageSavePojo.getEnableStageWarningColor());
            paasStageEntity.setStageWarningColor(stageSavePojo.getStageWarningColor());
            JSONArray executor = Objects.isNull(stageSavePojo.getExecutor()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageSavePojo.getExecutor()));
            paasStageEntity.setExecutor(executor);
            JSONArray preConditions = Objects.isNull(stageSavePojo.getPreConditions()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageSavePojo.getPreConditions()));
            paasStageEntity.setPreConditions(preConditions.toJSONString());
            Integer allowSkipStage = Objects.isNull(stageSavePojo.getAllowSkipStage()) ? 0 : stageSavePojo.getAllowSkipStage();
            paasStageEntity.setAllowSkipStage(allowSkipStage);
            Integer openStatus = Objects.isNull(stageSavePojo.getOpenStatus()) ? 0 : stageSavePojo.getOpenStatus();
            paasStageEntity.setOpenStatus(openStatus);
            Integer businessRelatedStatus  = Objects.isNull(stageSavePojo.getBusinessRelatedStatus()) ? 0 : stageSavePojo.getBusinessRelatedStatus();
            paasStageEntity.setBusinessRelatedStatus(businessRelatedStatus);
            Integer allowReactive = Objects.isNull(stageSavePojo.getAllowReactive()) ? 0 : stageSavePojo.getAllowReactive();
            paasStageEntity.setAllowReactive(allowReactive);
            JSONArray allowReactiveStage = Objects.isNull(stageSavePojo.getAllowReactiveStage()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageSavePojo.getAllowReactiveStage()));
            paasStageEntity.setAllowReactiveStage(allowReactiveStage);
            paasStageEntity.setEnableAutoJump(Objects.isNull(stageSavePojo.getEnableAutoJump()) ? 0 : stageSavePojo.getEnableAutoJump());
            paasStageEntity.setEnableJumpEnd(Objects.isNull(stageSavePojo.getEnableJumpEnd()) ? 1 : stageSavePojo.getEnableJumpEnd());
            Integer isDefault = Objects.isNull(stageSavePojo.getIsDefault()) ? 0 : stageSavePojo.getIsDefault();
            paasStageEntity.setIsDefault(isDefault);
            paasStageEntity.setLinkOption(stageSavePojo.getLinkOption());
            paasStageEntity.setDel(DelEnum.NORMAL.getDel());
            paasStageEntity.setUpdateTime(DateTimeUtil.getInt());
            paasStageEntity.setId(stageSavePojo.getId());
            if (Objects.nonNull(stageHandle)) {
                stageHandle.stageSaveSettingAdvance(paasStageEntity, stageSavePojo, StageSettingEnum.MAIN_SAVE.getCode());
            }
            paasStageEntityList.add(paasStageEntity);
        }
        return paasStageEntityList;
    }

    /**
     * 封装阶段实体
     * @param corpid
     * @param formId
     * @param stageProcessId
     * @param stageSavePojoList
     * @return
     */
    public List<PaasStageEntity> getPaasStageEntity(String corpid, Long formId, Long stageProcessId, List<StageSavePojo> stageSavePojoList) {
        return getPaasStageEntity(corpid, formId, stageProcessId, stageSavePojoList, null);
    }

    public List<PaasStageEntity> getPaasStageEntity4Copy(String corpid, Long formId, Long stageProcessId, List<StageSavePojo> stageSavePojoList, StageHandle stageHandle) {
        if (CollectionsUtil.isEmpty(stageSavePojoList)) {
            return new ArrayList<>();
        }
        List<PaasStageEntity> paasStageEntityList = new ArrayList<>(stageSavePojoList.size());
        for (StageSavePojo stageSavePojo : stageSavePojoList) {
            PaasStageEntity paasStageEntity = new PaasStageEntity();
            paasStageEntity.setCorpid(corpid);
            paasStageEntity.setFormId(formId);
            paasStageEntity.setStageProcessId(stageProcessId);
            paasStageEntity.setName(stageSavePojo.getName());
            paasStageEntity.setCode(stageSavePojo.getCode());
            paasStageEntity.setIntoProportion(stageSavePojo.getIntoProportion());
            paasStageEntity.setOutProportion(stageSavePojo.getOutProportion());
            paasStageEntity.setType(stageSavePojo.getType());
            paasStageEntity.setEnable(stageSavePojo.getEnable());
            paasStageEntity.setSort(stageSavePojo.getSort());
            Integer stayLimit = Objects.isNull(stageSavePojo.getStayLimit()) ? 0 : stageSavePojo.getStayLimit();
            paasStageEntity.setStayLimit(stayLimit);
            paasStageEntity.setStayLimitTime(stageSavePojo.getStayLimitTime());
            paasStageEntity.setStayLimitTimeUnit(stageSavePojo.getStayLimitTimeUnit());
            paasStageEntity.setEnableStageWarningColor(Objects.isNull(stageSavePojo.getEnableStageWarningColor()) ? 0 : stageSavePojo.getEnableStageWarningColor());
            paasStageEntity.setStageWarningColor(stageSavePojo.getStageWarningColor());
            JSONArray executor = Objects.isNull(stageSavePojo.getExecutor()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageSavePojo.getExecutor()));
            paasStageEntity.setExecutor(executor);
            JSONArray preConditions = Objects.isNull(stageSavePojo.getPreConditions()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageSavePojo.getPreConditions()));
            paasStageEntity.setPreConditions(preConditions.toJSONString());
            Integer allowSkipStage = Objects.isNull(stageSavePojo.getAllowSkipStage()) ? 0 : stageSavePojo.getAllowSkipStage();
            paasStageEntity.setAllowSkipStage(allowSkipStage);
            Integer openStatus = Objects.isNull(stageSavePojo.getOpenStatus()) ? 0 : stageSavePojo.getOpenStatus();
            paasStageEntity.setOpenStatus(openStatus);
            Integer businessRelatedStatus  = Objects.isNull(stageSavePojo.getBusinessRelatedStatus()) ? 0 : stageSavePojo.getBusinessRelatedStatus();
            paasStageEntity.setBusinessRelatedStatus(businessRelatedStatus);
            Integer allowReactive = Objects.isNull(stageSavePojo.getAllowReactive()) ? 0 : stageSavePojo.getAllowReactive();
            paasStageEntity.setAllowReactive(allowReactive);
            JSONArray allowReactiveStage = Objects.isNull(stageSavePojo.getAllowReactiveStage()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageSavePojo.getAllowReactiveStage()));
            paasStageEntity.setAllowReactiveStage(allowReactiveStage);
            paasStageEntity.setEnableAutoJump(Objects.isNull(stageSavePojo.getEnableAutoJump()) ? 0 : stageSavePojo.getEnableAutoJump());
            paasStageEntity.setEnableJumpEnd(Objects.isNull(stageSavePojo.getEnableJumpEnd()) ? 1 : stageSavePojo.getEnableJumpEnd());
            Integer isDefault = Objects.isNull(stageSavePojo.getIsDefault()) ? 0 : stageSavePojo.getIsDefault();
            paasStageEntity.setIsDefault(isDefault);
            paasStageEntity.setLinkOption(stageSavePojo.getLinkOption());
            paasStageEntity.setDel(DelEnum.NORMAL.getDel());
            paasStageEntity.setAddTime(DateTimeUtil.getInt());
            paasStageEntity.setUpdateTime(DateTimeUtil.getInt());
            paasStageEntity.setId(stageSavePojo.getId());
            if (Objects.nonNull(stageHandle)) {
                stageHandle.stageSaveSettingAdvance(paasStageEntity, stageSavePojo, StageSettingEnum.MAIN_COPY.getCode());
            }
            paasStageEntityList.add(paasStageEntity);
        }
        return paasStageEntityList;
    }

    public List<PaasStageEntity> getPaasStageEntity4Copy(String corpid, Long formId, Long stageProcessId, List<StageSavePojo> stageSavePojoList) {
        return getPaasStageEntity4Copy(corpid, formId, stageProcessId, stageSavePojoList, null);
    }

    /**
     * 封装流程返回
     * @param stageProcessEntity
     * @return
     */
    private StageProcessGetPojo getStageProcessGetPojo(StageProcessEntity stageProcessEntity) {
        StageProcessGetPojo stageProcessGetPojo = new StageProcessGetPojo();
        BeanUtil.copyProperties(stageProcessEntity, stageProcessGetPojo);
        JSONArray allowNewSelectUser = Objects.isNull(stageProcessEntity.getAllowNewSelectUser()) ? new JSONArray() : stageProcessEntity.getAllowNewSelectUser();
        stageProcessGetPojo.setAllowNewSelectUser(allowNewSelectUser.toJavaList(OptionalRangeEntity.class));
        JSONArray triggerCondition = Objects.isNull(stageProcessEntity.getTriggerCondition()) ? new JSONArray() : stageProcessEntity.getTriggerCondition();
        stageProcessGetPojo.setTriggerCondition(triggerCondition.toJavaList(FilterConditionsPoJo.class));

        return stageProcessGetPojo;
    }

    /**
     * 复制阶段和阶段任务
     * @param stageProcessAddDTO
     * @param stageProcessEntity
     * @throws XbbException
     */
    private void copyStage(StageProcessAddDTO stageProcessAddDTO, StageProcessEntity stageProcessEntity) throws XbbException {
        String corpid = stageProcessAddDTO.getCorpid();
        Integer saasMark = stageProcessAddDTO.getSaasMark();
        Integer businessType = stageProcessAddDTO.getBusinessType();
        Long formId = stageProcessAddDTO.getFormId();
        Long stageProcessId = stageProcessAddDTO.getId();
        //复制阶段
        List<PaasStageEntity> stageEntityList = stageHelp.getStageEntitys(corpid, saasMark, businessType, formId, stageProcessId);
        if (CollectionsUtil.isEmpty(stageEntityList)) {
            return;
        }
        Map<Long, PaasStageEntity> oldStageMap = new HashMap<>(stageEntityList.size());
        stageEntityList.forEach(item -> {
            oldStageMap.put(item.getId(), item);
            String code = UUID.randomUUID().toString();
            code = code.replace("-", "");
            item.setId(null);
            item.setStageProcessId(stageProcessEntity.getId());
            item.setCode(code);
            item.setUpdateTime(DateTimeUtil.getInt());
            item.setAddTime(DateTimeUtil.getInt());
        });
        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        stageHandle.insertBatch(stageEntityList);

        //复制工作流
        List<StageWorkflowEntity> stageWorkflowEntityList = stageHelp.getStageWorkflowEntity(corpid, formId, stageProcessId);
        if (CollectionsUtil.isNotEmpty(stageWorkflowEntityList)) {
            for (StageWorkflowEntity stageWorkflowEntity : stageWorkflowEntityList) {
                PaasStageEntity newPaasStageEntity = oldStageMap.get(stageWorkflowEntity.getStageId());
                PaasStageEntity newRelatedStageEntity = oldStageMap.get(stageWorkflowEntity.getRelatedStageId());
                if (Objects.nonNull(newPaasStageEntity) && Objects.nonNull(newRelatedStageEntity)) {
                    long now = DateTimeUtil.getInt();
                    stageWorkflowEntity.setId(null);
                    stageWorkflowEntity.setStageProcessId(newPaasStageEntity.getStageProcessId());
                    stageWorkflowEntity.setStageId(newPaasStageEntity.getId());
                    stageWorkflowEntity.setRelatedStageId(newRelatedStageEntity.getId());
                    stageWorkflowEntity.setAddTime(now);
                    stageWorkflowEntity.setUpdateTime(now);
                }
            }
            stageWorkflowModel.insertBatch(stageWorkflowEntityList);
        }
        //新建结束后置动作
        List<PaasStageEntity> updateStageEntityList = getUpdateStageEntity(stageEntityList, oldStageMap);
        if (CollectionsUtil.isNotEmpty(updateStageEntityList)) {
            stageHandle.updateBatch(stageEntityList, corpid);
        }

        //复制阶段任务
        List<StageWorkEntity> stageWorkEntityList = stageHelp.getStageWorkEntityByProcess(corpid, formId, stageProcessId);
        copyStageWork(stageWorkEntityList, oldStageMap);
    }

    /**
     * 获取需要更新的阶段实体
     * @param paasStageEntityList  阶段实体列表
     * @param oldStageMap 阶段映射
     * @return 需要继续更新的阶段实体
     */
    private List<PaasStageEntity> getUpdateStageEntity(List<PaasStageEntity> paasStageEntityList, Map<Long, PaasStageEntity> oldStageMap) {
        if (CollectionsUtil.isEmpty(paasStageEntityList)) {
            return new ArrayList<>();
        }
        List<PaasStageEntity> updatePaasStageEntityList = new ArrayList<>();
        for (PaasStageEntity paasStageEntity : paasStageEntityList) {
            JSONArray allowReactiveStage = Objects.isNull(paasStageEntity.getAllowReactiveStage()) ? new JSONArray() : paasStageEntity.getAllowReactiveStage();
            if (CollectionsUtil.isEmpty(allowReactiveStage)) {
                   continue;
            }
            List<Long> stageIdList = allowReactiveStage.toJavaList(Long.class);
            List<Long> newStageIdList = new ArrayList<>(stageIdList.size());
            for (Long id : stageIdList) {
                PaasStageEntity newStageEntity = oldStageMap.get(id);
                if (Objects.nonNull(newStageEntity) && Objects.equals(newStageEntity.getEnable(), EnableEnum.OPEN.getCode())) {
                    newStageIdList.add(newStageEntity.getId());
                }
            }
            JSONArray newAllowReactiveStage = JSONArray.parseArray(JSON.toJSONString(newStageIdList));
            paasStageEntity.setAllowReactiveStage(newAllowReactiveStage);
            updatePaasStageEntityList.add(paasStageEntity);
        }
        return updatePaasStageEntityList;
    }

    /**
     * 复制阶段任务
     * @param stageWorkEntityList
     * @param paasStageEntityMap
     */
    private void copyStageWork(List<StageWorkEntity> stageWorkEntityList, Map<Long, PaasStageEntity> paasStageEntityMap) {

        if (CollectionsUtil.isEmpty(stageWorkEntityList)) {
            return;
        }
        stageWorkEntityList.forEach(item -> {
            PaasStageEntity paasStageEntity = paasStageEntityMap.get(item.getStageId());
            if (Objects.isNull(paasStageEntity)) {
                return;
            }
            item.setId(null);
            item.setStageCode(paasStageEntity.getCode());
            item.setStageId(paasStageEntity.getId());
            item.setStageProcessId(paasStageEntity.getStageProcessId());
            item.setUpdateTime(DateTimeUtil.getInt());
            item.setAddTime(DateTimeUtil.getInt());
        });
        stageWorkModel.insertBatch(stageWorkEntityList);
    }

    /**
     * 阶段流程强校验
     * @param stageProcessEntity 阶段流程实体
     * @throws XbbException exception
     */
    private void checkStageProcess(StageProcessEntity stageProcessEntity) throws XbbException {
        String corpid = stageProcessEntity.getCorpid();
        Long formId = stageProcessEntity.getFormId();
        JSONArray triggerCondition = Objects.isNull(stageProcessEntity.getTriggerCondition()) ? new JSONArray() : stageProcessEntity.getTriggerCondition();
        List<FilterConditionsPoJo> filterConditionsPoJoList = triggerCondition.toJavaList(FilterConditionsPoJo.class);
        if (CollectionsUtil.isNotEmpty(filterConditionsPoJoList)) {
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            Map<String, FieldAttrEntity> thisExplainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
            BusinessRuleConditionHelp.validateStagePreCondition(filterConditionsPoJoList, thisExplainMap, I18nMessageUtil.getMessage(I18nStringConstant.STAGE_TRIGGER_CONDITION));
        }
    }

    /**
     * 获取机会某个form的某个版本的阶段
     * @param stageProcessGetExceptDTO
     * @param typeIn
     * @return java.util.List<? extends com.xbongbong.paas.domain.entity.PaasStageEntity>
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private List<? extends PaasStageEntity> getPaasStageList(StageProcessGetExceptDTO stageProcessGetExceptDTO, List<Integer> typeIn) {
        String corpid = stageProcessGetExceptDTO.getCorpid();
        Long formId = stageProcessGetExceptDTO.getFormId();
        Long stageProcessId = stageProcessGetExceptDTO.getId();
        StageFindStrategy stageFindStrategy = StageFindFactory.getStageFindStrategy(stageProcessGetExceptDTO.getSaasMark(), stageProcessGetExceptDTO.getBusinessType());
        return stageFindStrategy.findStageList(corpid, new StageFindPojo(formId, stageProcessId, EnableEnum.OPEN, typeIn));
    }

    @Override
    public void validateMultiVersionDefaultStageProcess(List<FieldAttrEntity> explains, String corpid, Long formId) throws XbbException {
        // 阶段默认版本相关的校验
        for (FieldAttrEntity fieldEntity : explains) {
            if (Objects.equals(FieldTypeEnum.STAGE_THRUSTER.getType(), fieldEntity.getFieldType())) {
                if (Objects.equals(fieldEntity.getStageMultiVersion(), 1)) {
                    // 开启多版本启用的开关时，必须选择一个默认版本
                    if (Objects.isNull(fieldEntity.getDefaultStageProcessId()) || Objects.equals(fieldEntity.getDefaultStageProcessId(), 0L)) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238076);
                    }
                    // 校验默认版本必须是启用的未被删除的未归档的
                    StageProcessEntity stageProcess = stageProcessModel.getByKey(fieldEntity.getDefaultStageProcessId(), corpid);
                    if (Objects.isNull(stageProcess) || Objects.equals(stageProcess.getDel(), DelEnum.DELETE.getDel())) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238075);
                    }
                    if (Objects.equals(stageProcess.getEnable(), EnableEnum.CLOSE.getCode()) || Objects.equals(stageProcess.getIsArchive(), ArchivedEnum.ARCHIVED.getCode())) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238078);
                    }
                } else {
                    // 如果存在多个启用的版本，则不允许关闭多版本启用的开关时
                    if (stageProcessModel.isEnableMultiStageProcessVersion(corpid, formId)) {
                        throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238077);
                    }
                }
            }
        }
    }
}
